home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Linux Cubed Series 7: Sunsite
/
Linux Cubed Series 7 - Sunsite Vol 1.iso
/
system
/
network
/
samba
/
patches
/
samba-1.043
/
samba-1
Wrap
Text File
|
1995-11-07
|
180KB
|
6,168 lines
diff -u -r --new-file last-version/docs/smb.conf.5 samba-1.9.14p3/docs/smb.conf.5
--- last-version/docs/smb.conf.5 Sun Sep 17 10:28:23 1995
+++ samba-1.9.14p3/docs/smb.conf.5 Sun Nov 5 11:35:38 1995
@@ -1510,7 +1510,7 @@
The string can contain the macros %o and %n which are substituted for
the old and new passwords respectively. It can aso contain the
-standard macros \n \r \t and \s to give line-feed, carriage-return,
+standard macros \\n \\r \\t and \\s to give line-feed, carriage-return,
tab and space.
The string can also contain a * which matches any sequence of
@@ -1524,11 +1524,11 @@
then no string is expected.
.B Example:
- passwd chat = "*Enter OLD password*" %o\n "*Enter NEW password*" %n\n \
- "*Reenter NEW password*" %n\n "*Password changed*"
+ passwd chat = "*Enter OLD password*" %o\\n "*Enter NEW password*" %n\\n \\
+ "*Reenter NEW password*" %n\\n "*Password changed*"
.B Default:
- passwd chat = *old*password* %o\n *new*password* %n\n *new*password* %n\n *changed*
+ passwd chat = *old*password* %o\\n *new*password* %n\\n *new*password* %n\\n *changed*
.SS passwd program (G)
The name of a program that can be used to set user passwords.
diff -u -r --new-file last-version/source/Makefile samba-1.9.14p3/source/Makefile
--- last-version/source/Makefile Thu Sep 21 20:24:34 1995
+++ samba-1.9.14p3/source/Makefile Tue Nov 7 22:58:21 1995
@@ -422,7 +422,8 @@
CFLAGS = $(CFLAGS5) $(DCE_FLAGS) $(DES_FLAGS) $(PASSWD_FLAGS) $(VTP_FLAGS)
LIBS = $(LIBS1) $(LIBSM) $(DCE_LIBS) $(DES_LIB)
-PROGS = smbd smbclient nmbd testparm testprns smbrun smbstatus smbpasswd
+PROGS1 = smbd smbclient nmbd testparm testprns smbrun smbstatus smbpasswd
+PROGS = $(PROGS1) nmbd2
SCRIPTS = smbtar
all : CHECK $(PROGS)
@@ -436,8 +437,10 @@
INCLUDES2 = pcap.h trans2.h reply.h
INCLUDES = $(INCLUDES1) $(INCLUDES2)
-UTILOBJ = util.o system.o charset.o kanji.o fault.o smbencrypt.o charcnv.o
-PARAMOBJ = $(UTILOBJ) loadparm.o params.o pcap.o access.o username.o ufc.o smbpass.o
+UTILOBJ1 = util.o system.o charset.o kanji.o fault.o smbencrypt.o charcnv.o
+UTILOBJ = $(UTILOBJ1) md4.o
+PARAMOBJ1 = $(UTILOBJ) loadparm.o params.o pcap.o access.o username.o
+PARAMOBJ = $(PARAMOBJ1) ufc.o smbpass.o
SMBDOBJ1 = $(PARAMOBJ) trans2.o message.o dir.o printing.o locking.o
SMBDOBJ2 = ipc.o reply.o mangle.o chgpasswd.o password.o
SMBDOBJ = $(SMBDOBJ1) $(SMBDOBJ2) $(VTP_OBJ)
@@ -457,9 +460,13 @@
@echo Linking smbrun
@$(CC) $(CFLAGS) -o smbrun smbrun.o $(LIBS)
-nmbd: nameserv.o $(UTILOBJ)
+nmbd: nameserv.o $(UTILOBJ)
@echo Linking nmbd
@$(CC) $(CFLAGS) -o nmbd nameserv.o $(UTILOBJ) $(LIBS)
+
+nmbd2: nameserv2.o nmblib.o $(UTILOBJ)
+ @echo Linking nmbd2
+ @$(CC) $(CFLAGS) -o nmbd2 nameserv2.o nmblib.o $(UTILOBJ) $(LIBS)
smbclient: client.o clitar.o $(UTILOBJ)
@echo Linking smbclient
diff -u -r --new-file last-version/source/change-log samba-1.9.14p3/source/change-log
--- last-version/source/change-log Sat Nov 4 23:21:02 1995
+++ samba-1.9.14p3/source/change-log Tue Nov 7 22:59:06 1995
@@ -1617,9 +1617,18 @@
- made rename and unlink look at share locks on file
- clitar memory leak fix from jjm@jjm.com
- added -p option to smbstatus to list smbd processes
+ - added rename to the client
- released p2
+ - fixed SMBmv for case where the destination exists
+ - man page patch from michal@ellpspace.math.ualberta.ca (Michal Jaegermann)
+ - once again redid the time handling, but finally explained what
+ is going on, this is written up in TIME.txt. The "kludge-GMT" used
+ by NT is a bastard and led to a lot of the confusion
+ - kanji patch from fujita@ainix.isac.co.jp (Takashi Fujita)
+ - is08859-1 patches from eauth@mail.cso.co.at
+ - starting rewriting nmbd, new nmbd is nmbd2, old one still around
+ for time being
-
==========
todo:
@@ -1653,6 +1662,10 @@
document cnvchar stuff
allow smbd to serve user and group lists to win95
+
+document homes behaviour with WinDD
+
+apparently WfWg doesn't like the password server stuff in 1.9.14. Why?
UNRESOLVED PROBLEMS
===================
diff -u -r --new-file last-version/source/client.c samba-1.9.14p3/source/client.c
--- last-version/source/client.c Sat Nov 4 21:31:10 1995
+++ samba-1.9.14p3/source/client.c Tue Nov 7 13:59:55 1995
@@ -444,12 +444,12 @@
****************************************************************************/
static void display_finfo(file_info *finfo)
{
- time_t t = finfo->mtime - DSTDiff(finfo->mtime);
+ time_t t = finfo->mtime; /* the time is assumed to be passed as GMT */
DEBUG(0,(" %-30s%7.7s%10d %s",
CNV_LANG(finfo->name),
attrib_string(finfo->mode),
finfo->size,
- asctime(LocalTime(&t,0))));
+ asctime(LocalTime(&t,GMT_TO_LOCAL))));
}
/****************************************************************************
@@ -492,7 +492,8 @@
{
finfo->mode = CVAL(p,21);
- finfo->ctime = make_unix_date(p+22,True);
+ /* this date is converted to GMT by make_unix_date */
+ finfo->ctime = make_unix_date(p+22);
finfo->mtime = finfo->atime = finfo->ctime;
finfo->size = IVAL(p,26);
strcpy(finfo->name,p+30);
@@ -516,9 +517,10 @@
case 1: /* OS/2 understands this */
if (finfo)
{
- finfo->ctime = make_unix_date2(p+4,True);
- finfo->atime = make_unix_date2(p+8,True);
- finfo->mtime = make_unix_date2(p+12,True);
+ /* these dates are converted to GMT by make_unix_date */
+ finfo->ctime = make_unix_date2(p+4);
+ finfo->atime = make_unix_date2(p+8);
+ finfo->mtime = make_unix_date2(p+12);
finfo->size = IVAL(p,16);
finfo->mode = CVAL(p,24);
strcpy(finfo->name,p+27);
@@ -528,9 +530,10 @@
case 2: /* this is what OS/2 uses mostly */
if (finfo)
{
- finfo->ctime = make_unix_date2(p+4,True);
- finfo->atime = make_unix_date2(p+8,True);
- finfo->mtime = make_unix_date2(p+12,True);
+ /* these dates are converted to GMT by make_unix_date */
+ finfo->ctime = make_unix_date2(p+4);
+ finfo->atime = make_unix_date2(p+8);
+ finfo->mtime = make_unix_date2(p+12);
finfo->size = IVAL(p,16);
finfo->mode = CVAL(p,24);
strcpy(finfo->name,p+31);
@@ -541,9 +544,10 @@
case 3:
if (finfo)
{
- finfo->ctime = make_unix_date2(p+8,True);
- finfo->atime = make_unix_date2(p+12,True);
- finfo->mtime = make_unix_date2(p+16,True);
+ /* these dates are probably like the other ones */
+ finfo->ctime = make_unix_date2(p+8);
+ finfo->atime = make_unix_date2(p+12);
+ finfo->mtime = make_unix_date2(p+16);
finfo->size = IVAL(p,20);
finfo->mode = CVAL(p,28);
strcpy(finfo->name,p+33);
@@ -553,9 +557,10 @@
case 4:
if (finfo)
{
- finfo->ctime = make_unix_date2(p+8,True);
- finfo->atime = make_unix_date2(p+12,True);
- finfo->mtime = make_unix_date2(p+16,True);
+ /* these dates are probably like the other ones */
+ finfo->ctime = make_unix_date2(p+8);
+ finfo->atime = make_unix_date2(p+12);
+ finfo->mtime = make_unix_date2(p+16);
finfo->size = IVAL(p,20);
finfo->mode = CVAL(p,28);
strcpy(finfo->name,p+37);
@@ -565,17 +570,24 @@
case 260: /* NT uses this, but also accepts 2 */
if (finfo)
{
- extern int serverzone;
int ret = SVAL(p,0);
int namelen;
p += 4; /* next entry offset */
p += 4; /* fileindex */
+
+ /* these dates appear to arrive in a weird way. It seems to
+ be localtime plus the serverzone given in the initial
+ connect. This is GMT when DST is not in effect and one
+ hour from GMT otherwise. Can this really be right??
+
+ I suppose this could be called kludge-GMT. Is is the GMT
+ you get by using the current DST setting on a different
+ localtime. It will be cheap to calculate, I suppose, as
+ no DST tables will be needed */
+
finfo->ctime = interpret_long_date(p); p += 8;
finfo->atime = interpret_long_date(p); p += 8;
finfo->mtime = interpret_long_date(p); p += 8; p += 8;
- finfo->mtime += DSTDiff(finfo->mtime) - serverzone;
- finfo->ctime += DSTDiff(finfo->ctime) - serverzone;
- finfo->atime += DSTDiff(finfo->atime) - serverzone;
finfo->size = IVAL(p,0); p += 8;
p += 8; /* alloc size */
finfo->mode = CVAL(p,0); p += 4;
@@ -1161,12 +1173,15 @@
}
strcpy(finfo.name,rname);
+
if (!finfo1)
{
finfo.mode = SVAL(inbuf,smb_vwv3);
- finfo.mtime = IVAL(inbuf,smb_vwv4);
- finfo.size = IVAL(inbuf,smb_vwv6);
+ /* these times arrive as LOCAL time, using the DST offset
+ corresponding to that time, we convert them to GMT */
+ finfo.mtime = make_unix_date3(inbuf+smb_vwv4);
finfo.atime = finfo.ctime = finfo.mtime;
+ finfo.size = IVAL(inbuf,smb_vwv6);
}
DEBUG(3,("file %s attrib 0x%X\n",CNV_LANG(finfo.name),finfo.mode));
@@ -1536,7 +1551,8 @@
if (lowercase)
strlower(finfo->name);
- if (!directory_exist(finfo->name) && sys_mkdir(finfo->name,0777) != 0)
+ if (!directory_exist(finfo->name,NULL) &&
+ sys_mkdir(finfo->name,0777) != 0)
{
DEBUG(0,("failed to create directory %s\n",CNV_LANG(finfo->name)));
strcpy(cur_dir,saved_curdir);
@@ -1834,25 +1850,18 @@
return;
}
- if (close_time != 0 && close_time != -1)
- close_time -= TimeDiff(close_time);
-
bzero(outbuf,smb_size);
set_message(outbuf,3,2 + strlen(rname),True);
if (finfo->mtime == 0 || finfo->mtime == -1)
- {
- time_t t = time(NULL);
- finfo->mtime = finfo->atime = finfo->ctime =
- t + GMT_TO_LOCAL*TimeDiff(t);
- }
-
+ finfo->mtime = finfo->atime = finfo->ctime = time(NULL);
+
CVAL(outbuf,smb_com) = SMBcreate;
SSVAL(outbuf,smb_tid,cnum);
setup_pkt(outbuf);
SSVAL(outbuf,smb_vwv0,finfo->mode);
- SIVAL(outbuf,smb_vwv1,finfo->mtime);
+ put_dos_date3(outbuf,smb_vwv1,finfo->mtime);
p = smb_buf(outbuf);
*p++ = 4;
@@ -1927,12 +1936,8 @@
SSVAL(outbuf,smb_tid,cnum);
setup_pkt(outbuf);
- SSVAL(outbuf,smb_vwv0,fnum);
- SIVAL(outbuf,smb_vwv1,close_time);
-
- DEBUG(3,("Setting date to %s (0x%X)",
- asctime(LocalTime(&finfo->mtime,LOCAL_TO_GMT)),
- finfo->mtime));
+ SSVAL(outbuf,smb_vwv0,fnum);
+ put_dos_date3(outbuf,smb_vwv1,close_time);
send_smb(outbuf);
receive_smb(inbuf,CLIENT_TIMEOUT);
@@ -2000,8 +2005,14 @@
dos_clean_name(rname);
- /* let the remote side decide the date */
- finfo.mtime = -1;
+ {
+ struct stat st;
+ if (!file_exist(lname,&st)) {
+ DEBUG(0,("%s does not exist\n"));
+ return;
+ }
+ finfo.mtime = st.st_mtime;
+ }
do_put(rname,lname,&finfo);
}
@@ -2054,6 +2065,7 @@
while (next_token(NULL,p,NULL))
{
+ struct stat st;
pstring cmd;
pstring tmpname;
FILE *f;
@@ -2078,7 +2090,7 @@
again1:
/* check if it's a directory */
- if (directory_exist(lname))
+ if (directory_exist(lname,&st))
{
if (!recurse) continue;
sprintf(quest,"Put directory %s? ",lname);
@@ -2115,8 +2127,8 @@
/* null size so do_put knows to ignore it */
finfo.size = -1;
- /* let the remote side decide the date */
- finfo.mtime = -1;
+ /* set the date on the file */
+ finfo.mtime = st.st_mtime;
do_put(rname,lname,&finfo);
}
@@ -2584,8 +2596,9 @@
ok = next_token(NULL,buf,NULL);
if (ok && (sys_stat(buf,&sbuf) == 0))
{
- newer_than = sbuf.st_mtime + GMT_TO_LOCAL*TimeDiff(sbuf.st_mtime);
- DEBUG(1,("Getting files newer than %s",asctime(LocalTime(&newer_than,0))));
+ newer_than = sbuf.st_mtime;
+ DEBUG(1,("Getting files newer than %s",
+ asctime(LocalTime(&newer_than,GMT_TO_LOCAL))));
}
else
newer_than = 0;
@@ -2895,8 +2908,9 @@
sec_mode = SVAL(inbuf,smb_vwv1);
max_xmit = SVAL(inbuf,smb_vwv2);
sesskey = IVAL(inbuf,smb_vwv6);
- servertime = make_unix_date(inbuf+smb_vwv8,False);
serverzone = SVALS(inbuf,smb_vwv10)*60;
+ /* this time is converted to GMT by make_unix_date */
+ servertime = make_unix_date(inbuf+smb_vwv8);
if (Protocol >= PROTOCOL_COREPLUS) {
readbraw_supported = ((SVAL(inbuf,smb_vwv5) & 0x1) != 0);
writebraw_supported = ((SVAL(inbuf,smb_vwv5) & 0x2) != 0);
@@ -2913,8 +2927,8 @@
max_xmit = IVAL(inbuf,smb_vwv3+1);
sesskey = IVAL(inbuf,smb_vwv7+1);
serverzone = SVALS(inbuf,smb_vwv15+1)*60;
+ /* this time arrives in real GMT */
servertime = interpret_long_date(inbuf+smb_vwv11+1);
- servertime -= serverzone;
crypt_len = CVAL(inbuf,smb_vwv16+1);
memcpy(cryptkey,smb_buf(inbuf),8);
if (IVAL(inbuf,smb_vwv9+1) & 1)
@@ -2937,7 +2951,7 @@
static BOOL done_time = False;
if (!done_time) {
DEBUG(1,("Server time is %sTimezone is UTC%+02.1f\n",
- asctime(LocalTime(&servertime,0)),
+ asctime(LocalTime(&servertime,GMT_TO_LOCAL)),
-(double)(serverzone/3600.0)));
done_time = True;
}
@@ -3805,12 +3819,13 @@
pstring query_host;
BOOL message = False;
- charset_initialise();
-
*query_host = 0;
DEBUGLEVEL = 2;
dbf = stdout;
+
+ TimeInit();
+ charset_initialise();
pid = getpid();
uid = getuid();
diff -u -r --new-file last-version/source/clitar.c samba-1.9.14p3/source/clitar.c
--- last-version/source/clitar.c Sat Nov 4 23:05:01 1995
+++ samba-1.9.14p3/source/clitar.c Mon Nov 6 16:17:43 1995
@@ -441,7 +441,7 @@
{
finfo.mode = SVAL(inbuf,smb_vwv3);
finfo.size = IVAL(inbuf,smb_vwv4);
- finfo.mtime = IVAL(inbuf,smb_vwv6);
+ finfo.mtime = make_unix_date3(inbuf+smb_vwv6);
finfo.atime = finfo.ctime = finfo.mtime;
}
@@ -856,7 +856,6 @@
*/
finfo->mtime = finfo->ctime = strtol(hb->dbuf.mtime, NULL, 8);
finfo->atime = time(NULL);
- finfo->atime += GMT_TO_LOCAL*TimeDiff(finfo->atime);
finfo->size = unoct(hb->dbuf.size, sizeof(hb->dbuf.size));
return True;
@@ -923,7 +922,7 @@
setup_pkt(outbuf);
SSVAL(outbuf,smb_vwv0,finfo.mode);
- SIVAL(outbuf,smb_vwv1,finfo.mtime);
+ put_dos_date3(outbuf,smb_vwv1,finfo.mtime);
p = smb_buf(outbuf);
*p++ = 4;
@@ -996,10 +995,10 @@
setup_pkt(outbuf);
SSVAL(outbuf,smb_vwv0,fnum);
- SIVAL(outbuf,smb_vwv1,finfo.mtime-TimeDiff(finfo.mtime));
+ put_dos_date3(outbuf,smb_vwv1,finfo.mtime);
DEBUG(3,("Setting date to %s (0x%X)",
- asctime(LocalTime(&finfo.mtime,LOCAL_TO_GMT)),
+ asctime(LocalTime(&finfo.mtime,GMT_TO_LOCAL)),
finfo.mtime));
send_smb(outbuf);
diff -u -r --new-file last-version/source/dir.c samba-1.9.14p3/source/dir.c
--- last-version/source/dir.c Thu Sep 21 20:58:46 1995
+++ samba-1.9.14p3/source/dir.c Tue Nov 7 12:46:56 1995
@@ -436,7 +436,7 @@
strcpy(filename,dname);
if ((strcmp(filename,mask) == 0) ||
- (name_convert(filename,dname,True,SNUM(cnum)) &&
+ (name_map_mangle(filename,True,SNUM(cnum)) &&
mask_match(filename,mask,False,False)))
{
if (isrootdir && (strequal(filename,"..") || strequal(filename,".")))
diff -u -r --new-file last-version/source/includes.h samba-1.9.14p3/source/includes.h
--- last-version/source/includes.h Sat Nov 4 21:51:34 1995
+++ samba-1.9.14p3/source/includes.h Tue Nov 7 12:49:21 1995
@@ -84,7 +84,6 @@
#define PASSWORD_LENGTH 16
#endif
-
/* here is the general includes section - with some ifdefs generated
by the previous section
*/
@@ -755,6 +754,13 @@
end of the platform specific sections
********************************************************************/
+#ifndef MAXINT
+#define MAXINT ((((unsigned)1)<<(sizeof(int)*8-1))-1)
+#endif
+
+#ifndef __STDC__
+#define const
+#endif
/* Now for some other grungy stuff */
#ifdef NO_GETSPNAM
@@ -958,6 +964,10 @@
#define F_WRLCK 0
#define F_UNLCK 0
#endif /* HAVE_FCNTL_LOCK == 0 */
+
+#ifdef NOSTRCASECMP
+#define strcasecmp(s1,s2) StrCaseCmp(s1,s2)
+#endif
#ifndef strcpy
#define strcpy(dest,src) StrCpy(dest,src)
diff -u -r --new-file last-version/source/ipc.c samba-1.9.14p3/source/ipc.c
--- last-version/source/ipc.c Sat Nov 4 18:58:24 1995
+++ samba-1.9.14p3/source/ipc.c Mon Nov 6 16:54:58 1995
@@ -458,6 +458,11 @@
struct pack_desc* desc,
print_queue_struct* queue, int n)
{
+ time_t t = queue->time;
+
+ /* the client expects localtime */
+ t += GMT_TO_LOCAL*TimeDiff(t);
+
PACKI(desc,"W",((snum%0xFF)<<8) | (queue->job%0xFF)); /* uJobId */
if (uLevel == 1) {
PACKS(desc,"B21",queue->user); /* szUserName */
@@ -709,8 +714,7 @@
/****************************************************************************
get info about a share
****************************************************************************/
-
-static int check_share_info(int uLevel, const char* id)
+static int check_share_info(int uLevel, char* id)
{
switch( uLevel ) {
case 0:
@@ -944,11 +948,13 @@
{
struct tm *t;
time_t unixdate = time(NULL);
- unixdate += GMT_TO_LOCAL*TimeDiff(unixdate);
+
+ put_dos_date3(p,0,unixdate); /* this is the time that is looked at by NT
+ in a "net time" operation */
- t = LocalTime(&unixdate,0);
+ /* the client expects to get localtime, not GMT */
+ t = LocalTime(&unixdate,GMT_TO_LOCAL);
- SIVAL(p,0,unixdate);
SIVAL(p,4,0); /* msecs ? */
CVAL(p,8) = t->tm_hour;
CVAL(p,9) = t->tm_min;
@@ -995,7 +1001,7 @@
DEBUG(3,("Set password for <%s>\n",user));
- if (!password_ok(user,pass1,strlen(pass1),NULL) ||
+ if (!password_ok(user,pass1,strlen(pass1),NULL,False) ||
!chgpasswd(user,pass1,pass2))
SSVAL(*rparam,0,NERR_badpass);
@@ -1128,7 +1134,7 @@
or <WWsTP> <WB21BB16B10zWWzDDz>
****************************************************************************/
static int check_printjob_info(struct pack_desc* desc,
- int uLevel, const char* id)
+ int uLevel, char* id)
{
desc->subformat = NULL;
switch( uLevel ) {
@@ -1766,7 +1772,7 @@
}
static int check_printdest_info(struct pack_desc* desc,
- int uLevel, const char* id)
+ int uLevel, char* id)
{
desc->subformat = NULL;
switch( uLevel ) {
diff -u -r --new-file last-version/source/kanji.h samba-1.9.14p3/source/kanji.h
--- last-version/source/kanji.h Thu Sep 21 20:49:48 1995
+++ samba-1.9.14p3/source/kanji.h Tue Nov 7 11:03:48 1995
@@ -27,9 +27,6 @@
#define _KANJI_H_
#ifdef KANJI
-#ifndef REPLACE_RENAME
-#define REPLACE_RENAME
-#endif
/* FOR SHIFT JIS CODE */
#define is_shift_jis(c) \
diff -u -r --new-file last-version/source/local.h samba-1.9.14p3/source/local.h
--- last-version/source/local.h Sun Oct 22 13:51:03 1995
+++ samba-1.9.14p3/source/local.h Sun Nov 5 12:37:52 1995
@@ -140,4 +140,9 @@
#define SMB_ALIGNMENT 1
+
+/* shall we support browse requests via a FIFO to nmbd? */
+#define ENABLE_FIFO 1
+
+
#endif
diff -u -r --new-file last-version/source/mangle.c samba-1.9.14p3/source/mangle.c
--- last-version/source/mangle.c Fri Sep 15 20:34:00 1995
+++ samba-1.9.14p3/source/mangle.c Tue Nov 7 12:33:19 1995
@@ -533,11 +533,8 @@
/****************************************************************************
convert a filename to DOS format. return True if successful.
****************************************************************************/
-BOOL name_convert(char *OutName,char *InName,BOOL need83,int snum)
+BOOL name_map_mangle(char *OutName,BOOL need83,int snum)
{
- /* initially just copy it */
- strcpy(OutName,unix2dos_format(InName,False));
-
/* apply any name mappings */
{
char *map = lp_mangled_map(snum);
diff -u -r --new-file last-version/source/md4.c samba-1.9.14p3/source/md4.c
--- last-version/source/md4.c Thu Jan 1 10:00:00 1970
+++ samba-1.9.14p3/source/md4.c Tue Nov 7 12:44:48 1995
@@ -0,0 +1,299 @@
+#ifdef SMB_PASSWD
+/*
+ This code is from rfc1186.
+*/
+
+ /*
+ ** ********************************************************************
+ ** md4.c -- Implementation of MD4 Message Digest Algorithm **
+ ** Updated: 2/16/90 by Ronald L. Rivest **
+ ** (C) 1990 RSA Data Security, Inc. **
+ ** ********************************************************************
+ */
+
+ /*
+ ** To use MD4:
+ ** -- Include md4.h in your program
+ ** -- Declare an MDstruct MD to hold the state of the digest
+ ** computation.
+ ** -- Initialize MD using MDbegin(&MD)
+ ** -- For each full block (64 bytes) X you wish to process, call
+ ** MDupdate(&MD,X,512)
+ ** (512 is the number of bits in a full block.)
+ ** -- For the last block (less than 64 bytes) you wish to process,
+ ** MDupdate(&MD,X,n)
+ ** where n is the number of bits in the partial block. A partial
+ ** block terminates the computation, so every MD computation
+ ** should terminate by processing a partial block, even if it
+ ** has n = 0.
+ ** -- The message digest is available in MD.buffer[0] ...
+ ** MD.buffer[3]. (Least-significant byte of each word
+ ** should be output first.)
+ ** -- You can print out the digest using MDprint(&MD)
+ */
+
+ /* Implementation notes:
+ ** This implementation assumes that ints are 32-bit quantities.
+ ** If the machine stores the least-significant byte of an int in the
+ ** least-addressed byte (e.g., VAX and 8086), then LOWBYTEFIRST
+ ** should be set to TRUE. Otherwise (e.g., SUNS), LOWBYTEFIRST
+ ** should be set to FALSE. Note that on machines with LOWBYTEFIRST
+ ** FALSE the routine MDupdate modifies has a side-effect on its input
+ ** array (the order of bytes in each word are reversed). If this is
+ ** undesired a call to MDreverse(X) can reverse the bytes of X back
+ ** into order after each call to MDupdate.
+ */
+
+#define TRUE 1
+#define FALSE 0
+
+ /* Compile-time includes
+ */
+
+#include <stdio.h>
+#include "md4.h"
+
+#define uchar unsigned char
+#define int16 unsigned short
+#define uint32 unsigned int
+
+#include "byteorder.h"
+
+ /* Compile-time declarations of MD4 "magic constants".
+ */
+#define I0 0x67452301 /* Initial values for MD buffer */
+#define I1 0xefcdab89
+#define I2 0x98badcfe
+#define I3 0x10325476
+#define C2 013240474631 /* round 2 constant = sqrt(2) in octal */
+#define C3 015666365641 /* round 3 constant = sqrt(3) in octal */
+ /* C2 and C3 are from Knuth, The Art of Programming, Volume 2
+ ** (Seminumerical Algorithms), Second Edition (1981), Addison-Wesley.
+ ** Table 2, page 660.
+ */
+
+#define fs1 3 /* round 1 shift amounts */
+#define fs2 7
+#define fs3 11
+#define fs4 19
+#define gs1 3 /* round 2 shift amounts */
+#define gs2 5
+#define gs3 9
+#define gs4 13
+#define hs1 3 /* round 3 shift amounts */
+#define hs2 9
+#define hs3 11
+#define hs4 15
+
+ /* Compile-time macro declarations for MD4.
+ ** Note: The "rot" operator uses the variable "tmp".
+ ** It assumes tmp is declared as unsigned int, so that the >>
+ ** operator will shift in zeros rather than extending the sign bit.
+ */
+#define f(X,Y,Z) ((X&Y) | ((~X)&Z))
+#define g(X,Y,Z) ((X&Y) | (X&Z) | (Y&Z))
+#define h(X,Y,Z) (X^Y^Z)
+#define rot(X,S) (tmp=X,(tmp<<S) | (tmp>>(32-S)))
+#define ff(A,B,C,D,i,s) A = rot((A + f(B,C,D) + X[i]),s)
+#define gg(A,B,C,D,i,s) A = rot((A + g(B,C,D) + X[i] + C2),s)
+#define hh(A,B,C,D,i,s) A = rot((A + h(B,C,D) + X[i] + C3),s)
+
+ /* MDprint(MDp)
+ ** Print message digest buffer MDp as 32 hexadecimal digits.
+ ** Order is from low-order byte of buffer[0] to high-order byte of
+ ** buffer[3].
+ ** Each byte is printed with high-order hexadecimal digit first.
+ ** This is a user-callable routine.
+ */
+ void
+ MDprint(MDp)
+ MDptr MDp;
+ { int i,j;
+ for (i=0;i<4;i++)
+ for (j=0;j<32;j=j+8)
+ printf("%02x",(MDp->buffer[i]>>j) & 0xFF);
+ }
+
+ /* MDbegin(MDp)
+ ** Initialize message digest buffer MDp.
+ ** This is a user-callable routine.
+ */
+ void
+ MDbegin(MDp)
+ MDptr MDp;
+ { int i;
+ MDp->buffer[0] = I0;
+ MDp->buffer[1] = I1;
+ MDp->buffer[2] = I2;
+ MDp->buffer[3] = I3;
+ for (i=0;i<8;i++) MDp->count[i] = 0;
+ MDp->done = 0;
+ }
+
+ /* MDreverse(X)
+ ** Reverse the byte-ordering of every int in X.
+ ** Assumes X is an array of 16 ints.
+ ** The macro revx reverses the byte-ordering of the next word of X.
+ */
+ void MDreverse(X)
+ unsigned int *X;
+ { register unsigned int t;
+ register unsigned int i;
+
+ for(i = 0; i < 16; i++) {
+ t = X[i];
+ SIVAL(X,i*4,t);
+ }
+ }
+
+ /* MDblock(MDp,X)
+ ** Update message digest buffer MDp->buffer using 16-word data block X.
+ ** Assumes all 16 words of X are full of data.
+ ** Does not update MDp->count.
+ ** This routine is not user-callable.
+ */
+ static void
+ MDblock(MDp,X)
+ MDptr MDp;
+ unsigned int *X;
+ {
+ register unsigned int tmp, A, B, C, D;
+ MDreverse(X);
+ A = MDp->buffer[0];
+ B = MDp->buffer[1];
+ C = MDp->buffer[2];
+ D = MDp->buffer[3];
+ /* Update the message digest buffer */
+ ff(A , B , C , D , 0 , fs1); /* Round 1 */
+ ff(D , A , B , C , 1 , fs2);
+ ff(C , D , A , B , 2 , fs3);
+ ff(B , C , D , A , 3 , fs4);
+ ff(A , B , C , D , 4 , fs1);
+ ff(D , A , B , C , 5 , fs2);
+ ff(C , D , A , B , 6 , fs3);
+ ff(B , C , D , A , 7 , fs4);
+ ff(A , B , C , D , 8 , fs1);
+ ff(D , A , B , C , 9 , fs2);
+ ff(C , D , A , B , 10 , fs3);
+ ff(B , C , D , A , 11 , fs4);
+ ff(A , B , C , D , 12 , fs1);
+ ff(D , A , B , C , 13 , fs2);
+ ff(C , D , A , B , 14 , fs3);
+ ff(B , C , D , A , 15 , fs4);
+ gg(A , B , C , D , 0 , gs1); /* Round 2 */
+ gg(D , A , B , C , 4 , gs2);
+ gg(C , D , A , B , 8 , gs3);
+ gg(B , C , D , A , 12 , gs4);
+ gg(A , B , C , D , 1 , gs1);
+ gg(D , A , B , C , 5 , gs2);
+ gg(C , D , A , B , 9 , gs3);
+ gg(B , C , D , A , 13 , gs4);
+ gg(A , B , C , D , 2 , gs1);
+ gg(D , A , B , C , 6 , gs2);
+ gg(C , D , A , B , 10 , gs3);
+ gg(B , C , D , A , 14 , gs4);
+ gg(A , B , C , D , 3 , gs1);
+ gg(D , A , B , C , 7 , gs2);
+ gg(C , D , A , B , 11 , gs3);
+ gg(B , C , D , A , 15 , gs4);
+ hh(A , B , C , D , 0 , hs1); /* Round 3 */
+ hh(D , A , B , C , 8 , hs2);
+ hh(C , D , A , B , 4 , hs3);
+ hh(B , C , D , A , 12 , hs4);
+ hh(A , B , C , D , 2 , hs1);
+ hh(D , A , B , C , 10 , hs2);
+ hh(C , D , A , B , 6 , hs3);
+ hh(B , C , D , A , 14 , hs4);
+ hh(A , B , C , D , 1 , hs1);
+ hh(D , A , B , C , 9 , hs2);
+ hh(C , D , A , B , 5 , hs3);
+ hh(B , C , D , A , 13 , hs4);
+ hh(A , B , C , D , 3 , hs1);
+ hh(D , A , B , C , 11 , hs2);
+ hh(C , D , A , B , 7 , hs3);
+ hh(B , C , D , A , 15 , hs4);
+ MDp->buffer[0] += A;
+ MDp->buffer[1] += B;
+ MDp->buffer[2] += C;
+ MDp->buffer[3] += D;
+ }
+
+ /* MDupdate(MDp,X,count)
+ ** Input: MDp -- an MDptr
+ ** X -- a pointer to an array of unsigned characters.
+ ** count -- the number of bits of X to use.
+ ** (if not a multiple of 8, uses high bits of last byte.)
+ ** Update MDp using the number of bits of X given by count.
+ ** This is the basic input routine for an MD4 user.
+ ** The routine completes the MD computation when count < 512, so
+ ** every MD computation should end with one call to MDupdate with a
+ ** count less than 512. A call with count 0 will be ignored if the
+ ** MD has already been terminated (done != 0), so an extra call with
+ ** count 0 can be given as a "courtesy close" to force termination
+ ** if desired.
+ */
+ void
+ MDupdate(MDp,X,count)
+ MDptr MDp;
+ unsigned char *X;
+ unsigned int count;
+ { unsigned int i, tmp, bit, byte, mask;
+ unsigned char XX[64];
+ unsigned char *p;
+ /* return with no error if this is a courtesy close with count
+ ** zero and MDp->done is true.
+ */
+ if (count == 0 && MDp->done) return;
+ /* check to see if MD is already done and report error */
+ if (MDp->done)
+ { printf("\nError: MDupdate MD already done."); return; }
+ /* Add count to MDp->count */
+ tmp = count;
+ p = MDp->count;
+ while (tmp)
+ { tmp += *p;
+ *p++ = tmp;
+ tmp = tmp >> 8;
+ }
+ /* Process data */
+ if (count == 512)
+ { /* Full block of data to handle */
+ MDblock(MDp,(unsigned int *)X);
+ }
+ else if (count > 512) /* Check for count too large */
+ { printf("\nError: MDupdate called with illegal count value %d."
+ ,count);
+ return;
+ }
+ else /* partial block -- must be last block so finish up */
+ { /* Find out how many bytes and residual bits there are */
+ byte = count >> 3;
+ bit = count & 7;
+ /* Copy X into XX since we need to modify it */
+ for (i=0;i<=byte;i++) XX[i] = X[i];
+ for (i=byte+1;i<64;i++) XX[i] = 0;
+ /* Add padding '1' bit and low-order zeros in last byte */
+ mask = 1 << (7 - bit);
+ XX[byte] = (XX[byte] | mask) & ~( mask - 1);
+ /* If room for bit count, finish up with this block */
+ if (byte <= 55)
+ { for (i=0;i<8;i++) XX[56+i] = MDp->count[i];
+ MDblock(MDp,(unsigned int *)XX);
+ }
+ else /* need to do two blocks to finish up */
+ { MDblock(MDp,(unsigned int *)XX);
+ for (i=0;i<56;i++) XX[i] = 0;
+ for (i=0;i<8;i++) XX[56+i] = MDp->count[i];
+ MDblock(MDp,(unsigned int *)XX);
+ }
+ /* Set flag saying we're done with MD computation */
+ MDp->done = 1;
+ }
+ }
+
+ /*
+ ** End of md4.c
+ */
+#else
+void md4_dummy() {;}
+#endif
diff -u -r --new-file last-version/source/md4.h samba-1.9.14p3/source/md4.h
--- last-version/source/md4.h Thu Jan 1 10:00:00 1970
+++ samba-1.9.14p3/source/md4.h Tue Nov 7 10:50:21 1995
@@ -0,0 +1,58 @@
+/*
+ This code is from rfc1186.
+*/
+
+ /*
+ ** ********************************************************************
+ ** md4.h -- Header file for implementation of **
+ ** MD4 Message Digest Algorithm **
+ ** Updated: 2/13/90 by Ronald L. Rivest **
+ ** (C) 1990 RSA Data Security, Inc. **
+ ** ********************************************************************
+ */
+
+ /* MDstruct is the data structure for a message digest computation.
+ */
+ typedef struct {
+ unsigned int buffer[4]; /* Holds 4-word result of MD computation */
+ unsigned char count[8]; /* Number of bits processed so far */
+ unsigned int done; /* Nonzero means MD computation finished */
+ } MDstruct, *MDptr;
+
+ /* MDbegin(MD)
+
+
+
+ ** Input: MD -- an MDptr
+ ** Initialize the MDstruct prepatory to doing a message digest
+ ** computation.
+ */
+ extern void MDbegin();
+
+ /* MDupdate(MD,X,count)
+ ** Input: MD -- an MDptr
+ ** X -- a pointer to an array of unsigned characters.
+ ** count -- the number of bits of X to use (an unsigned int).
+ ** Updates MD using the first "count" bits of X.
+ ** The array pointed to by X is not modified.
+ ** If count is not a multiple of 8, MDupdate uses high bits of
+ ** last byte.
+ ** This is the basic input routine for a user.
+ ** The routine terminates the MD computation when count < 512, so
+ ** every MD computation should end with one call to MDupdate with a
+ ** count less than 512. Zero is OK for a count.
+ */
+ extern void MDupdate();
+
+ /* MDprint(MD)
+ ** Input: MD -- an MDptr
+ ** Prints message digest buffer MD as 32 hexadecimal digits.
+ ** Order is from low-order byte of buffer[0] to high-order byte
+ ** of buffer[3].
+ ** Each byte is printed with high-order hexadecimal digit first.
+ */
+ extern void MDprint();
+
+ /*
+ ** End of md4.h
+ */
diff -u -r --new-file last-version/source/mksmbpasswd.sh samba-1.9.14p3/source/mksmbpasswd.sh
--- last-version/source/mksmbpasswd.sh Tue Jul 11 13:41:45 1995
+++ samba-1.9.14p3/source/mksmbpasswd.sh Sun Nov 5 15:46:37 1995
@@ -2,5 +2,5 @@
awk 'BEGIN {FS=":"
printf("#\n# SMB password file.\n#\n")
}
-{ printf( "%s:%s:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX:%s:%s:%s\n", $1, $3, $5, $6, $7) }
+{ printf( "%s:%s:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX:%s:%s:%s\n", $1, $3, $5, $6, $7) }
'
diff -u -r --new-file last-version/source/nameserv.c samba-1.9.14p3/source/nameserv.c
--- last-version/source/nameserv.c Fri Sep 22 17:39:32 1995
+++ samba-1.9.14p3/source/nameserv.c Tue Nov 7 14:08:34 1995
@@ -43,7 +43,6 @@
static int num_good_receives=0;
static pstring lookup="";
static int Client138=-1;
-
enum name_sources {LMHOSTS, REGISTER, SELF, DNS};
/* this is the structure used for the local netbios name table */
@@ -493,12 +492,13 @@
/****************************************************************************
interpret a node status response
****************************************************************************/
-static void interpret_node_status(char *inbuf,char *master)
+static void interpret_node_status(char *inbuf, char *master)
{
int level = master?3:0;
char *p = inbuf + 12 + name_len(inbuf+12) + 10;
int numnames = CVAL(p,0);
DEBUG(level,("received %d names\n",numnames));
+
p += 1;
while (numnames--)
{
@@ -508,6 +508,7 @@
StrnCpy(qname,p,15);
type = CVAL(p,15);
p += 16;
+
if (p[0] & 0x80) strcat(flags,"<GROUP> ");
if (p[0] & 0x60 == 0) strcat(flags,"B ");
if (p[0] & 0x60 == 1) strcat(flags,"P ");
@@ -649,8 +650,8 @@
/****************************************************************************
do a netbios name query to find someones IP
****************************************************************************/
-static BOOL name_query(char *name,char name_type,BOOL bcast,
- struct in_addr to_ip,struct in_addr *ip,void (*fn)())
+static BOOL name_query(char *name, char name_type, BOOL bcast,
+ struct in_addr to_ip, struct in_addr *ip, void (*fn)())
{
BOOL found=False;
pstring inbuf,outbuf;
@@ -738,7 +739,8 @@
/****************************************************************************
do a netbios name status to a host
****************************************************************************/
-static BOOL name_status(char *name,int type,struct in_addr to_ip,void (*fn)(),char *master)
+static BOOL name_status(char *name,int type,struct in_addr to_ip,void (*fn)(),
+ char *master)
{
pstring inbuf,outbuf;
static uint16 name_trn_id = 0x4262;
@@ -806,7 +808,7 @@
if (rcode==0 && ancount==1 && qdcount==0) {
DEBUG(fn?3:0,("Got a positive node status response from %s\n",
inet_ntoa(lastip)));
- interpret_node_status(inbuf,master);
+ interpret_node_status(inbuf, master);
return(True);
}
return(False);
@@ -1606,7 +1608,6 @@
first = False;
}
-
/****************************************************************************
process commands from the client
****************************************************************************/
@@ -1678,13 +1679,13 @@
static BOOL open_sockets(BOOL isdaemon,int port)
{
struct hostent *hp;
-
+
/* get host info */
if ((hp = Get_Hostbyname(myhostname)) == 0)
{
DEBUG(0,( "Get_Hostbyname: Unknown host. %s\n",myhostname));
return False;
- }
+ }
if (isdaemon)
Client = open_socket_in(SOCK_DGRAM, port,*lookup?3:0);
@@ -1702,8 +1703,10 @@
set_socket_options(Client138,"SO_BROADCAST");
set_socket_options(Client,user_socket_options);
+
+ DEBUG(3, ("Socket opened.\n"));
return True;
-}
+};
/****************************************************************************
@@ -1734,7 +1737,8 @@
Netmask = ip2;
}
- DEBUG(1,("Using IP %s ",inet_ntoa(myip)));
+ DEBUG(1,("Using IP %s ",inet_ntoa(myip))); /* core dump reported
+ doing this. Why?? XXXXX */
DEBUG(1,("broadcast %s ",inet_ntoa(bcast_ip)));
DEBUG(1,("netmask %s\n",inet_ntoa(Netmask)));
@@ -1797,6 +1801,8 @@
*lookup = *host_file = 0;
+ TimeInit();
+
charset_initialise();
strcpy(debugf,NMBLOGFILE);
@@ -1988,6 +1994,9 @@
DEBUG(2,("%s becoming a daemon\n",timestring()));
become_daemon();
}
+
+
+ DEBUG(3,("Opening sockets\n"));
if (open_sockets(is_daemon,port))
{
diff -u -r --new-file last-version/source/nameserv.h samba-1.9.14p3/source/nameserv.h
--- last-version/source/nameserv.h Thu Jan 1 10:00:00 1970
+++ samba-1.9.14p3/source/nameserv.h Tue Nov 7 22:17:38 1995
@@ -0,0 +1,130 @@
+/*
+ Unix SMB/Netbios implementation.
+ Version 1.9.
+ NBT netbios header - version 2
+ Copyright (C) Andrew Tridgell 1994-1995
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#define MAX_DGRAM_SIZE 576
+#define MIN_DGRAM_SIZE 12
+
+#define NMB_PORT 137
+#define DGRAM_PORT 138
+
+/* a netbios name structure */
+struct nmb_name {
+ char name[17];
+ char scope[64];
+ int name_type;
+};
+
+/* a resource record */
+struct res_rec {
+ struct nmb_name rr_name;
+ int rr_type;
+ int rr_class;
+ int ttl;
+ int rdlength;
+ char rdata[MAX_DGRAM_SIZE];
+};
+
+/* define a nmb packet. */
+struct nmb_packet
+{
+ struct {
+ int name_trn_id;
+ int opcode;
+ BOOL response;
+ struct {
+ BOOL bcast;
+ BOOL recursion_available;
+ BOOL recursion_desired;
+ BOOL trunc;
+ BOOL authoritative;
+ } nm_flags;
+ int rcode;
+ int qdcount;
+ int ancount;
+ int nscount;
+ int arcount;
+ } header;
+
+ struct {
+ struct nmb_name question_name;
+ int question_type;
+ int question_class;
+ } question;
+
+ struct res_rec *answers;
+ struct res_rec *nsrecs;
+ struct res_rec *additional;
+};
+
+
+/* a datagram - a simple structure at first, it would be good to parse
+ it properly later */
+struct dgram_packet {
+ struct {
+ int res;
+ int id;
+ struct in_addr ip;
+ int port;
+ int length;
+ int res2;
+ struct nmb_name source_name;
+ struct nmb_name dest_name;
+ } header;
+ int smbsize;
+ char smb_data[MAX_DGRAM_SIZE];
+};
+
+enum packet_type {NMB_PACKET, DGRAM_PACKET};
+
+/* define a structure used to queue packets. this will be a linked
+ list of nmb packets */
+struct packet_struct
+{
+ struct packet_struct *next;
+ struct packet_struct *prev;
+ struct in_addr ip;
+ int port;
+ int fd;
+ time_t timestamp;
+ enum packet_type packet_type;
+ union {
+ struct nmb_packet nmb;
+ struct dgram_packet dgram;
+ } packet;
+};
+
+
+/* this defines a list of network interfaces */
+struct net_interface {
+ struct net_interface *next;
+ struct in_addr ip;
+ struct in_addr bcast;
+ struct in_addr netmask;
+};
+
+
+/* prototypes */
+void free_nmb_packet(struct nmb_packet *nmb);
+void free_packet(struct packet_struct *packet);
+struct packet_struct *read_packet(int fd,enum packet_type packet_type);
+BOOL send_packet(struct packet_struct *p);
+struct packet_struct *receive_packet(int fd,enum packet_type type,int timeout);
diff -u -r --new-file last-version/source/nameserv2.c samba-1.9.14p3/source/nameserv2.c
--- last-version/source/nameserv2.c Thu Jan 1 10:00:00 1970
+++ samba-1.9.14p3/source/nameserv2.c Tue Nov 7 22:37:02 1995
@@ -0,0 +1,1980 @@
+/*
+ Unix SMB/Netbios implementation.
+ Version 1.9.
+ NBT netbios routines and daemon - version 2
+ Copyright (C) Andrew Tridgell 1994-1995
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include "includes.h"
+#include "nameserv.h"
+
+
+static void queue_packet(struct packet_struct *packet);
+
+
+extern int DEBUGLEVEL;
+
+/* the list of network interfaces */
+struct net_interface *interfaces = NULL;
+
+extern pstring debugf;
+extern int DEBUGLEVEL;
+
+extern pstring scope;
+
+static int browse_interval = BROWSE_INTERVAL;
+
+static BOOL dns_serve = False;
+static BOOL CanRecurse = True;
+
+extern struct in_addr lastip;
+extern int lastport;
+extern struct in_addr myip;
+extern struct in_addr bcast_ip;
+extern struct in_addr Netmask;
+extern pstring myhostname;
+static pstring host_file;
+static pstring myname="";
+static pstring lookup="";
+static int ClientNMB=-1;
+static int ClientDGRAM=-1;
+enum name_sources {LMHOSTS, REGISTER, SELF, DNS};
+
+/* this is the structure used for the local netbios name table */
+typedef struct
+{
+ time_t start_time;
+ int ttl;
+ struct in_addr ip;
+ struct in_addr master_ip;
+ BOOL found_master;
+ BOOL valid;
+ BOOL isgroup;
+ BOOL unicast;
+ char name[100];
+ int type;
+ int count;
+ enum name_sources source;
+} name_struct;
+
+
+static int num_names=0;
+static name_struct *names = NULL;
+
+#define NAMEVALID(i) names[i].valid
+#define ISGROUP(i) (names[i].isgroup)
+
+void process(void);
+
+/* are we running as a daemon ? */
+static BOOL is_daemon = False;
+
+/* machine comment */
+static pstring comment="";
+
+extern pstring user_socket_options;
+
+static void add_group_name(char *name);
+static void add_host_name(char *name,int type,struct in_addr *ip);
+static void dump_names(void);
+
+
+static BOOL got_bcast = False;
+static BOOL got_myip = False;
+static BOOL got_nmask = False;
+
+
+/****************************************************************************
+catch a sighup
+****************************************************************************/
+static int sig_hup()
+{
+ BlockSignals(True);
+
+ DEBUG(0,("Got SIGHUP - not implemented\n"));
+ dump_names();
+ if (!is_daemon)
+ exit(1);
+
+ BlockSignals(False);
+#ifndef DONT_REINSTALL_SIG
+ signal(SIGHUP,SIGNAL_CAST sig_hup);
+#endif
+ return(0);
+}
+
+/****************************************************************************
+catch a sigpipe
+****************************************************************************/
+static int sig_pipe()
+{
+ BlockSignals(True);
+
+ DEBUG(0,("Got SIGPIPE\n"));
+ if (!is_daemon)
+ exit(1);
+ BlockSignals(False);
+ return(0);
+}
+
+/****************************************************************************
+possibly continue after a fault
+****************************************************************************/
+static void fault_continue(void)
+{
+ static int errcount=0;
+
+ errcount++;
+
+ if (is_daemon && errcount<100)
+ process();
+
+ exit(1);
+}
+
+/****************************************************************************
+ true if two netbios names are equal
+****************************************************************************/
+static BOOL name_equal(char *s1,char *s2,int type1,int type2)
+{
+ char n1[20],n2[20];
+
+ if (type1 != type2) return(False);
+
+ StrnCpy(n1,s1,15);
+ StrnCpy(n2,s2,15);
+
+ trim_string(n1,NULL," ");
+ trim_string(n2,NULL," ");
+
+ return(strequal(n1,n2));
+}
+
+/****************************************************************************
+add a netbios name
+****************************************************************************/
+static int add_name(void)
+{
+ int i;
+
+ for (i=0;i<num_names;i++)
+ if (!names[i].valid)
+ break;
+
+ if (i==num_names) {
+ name_struct *n;
+ if (num_names == 0)
+ n = (name_struct *)malloc(sizeof(name_struct));
+ else
+ n = (name_struct *)realloc(names,sizeof(name_struct)*(num_names+1));
+ if (!n) {
+ DEBUG(0,("Can't malloc more names space!\n"));
+ return(-1);
+ }
+ i = num_names;
+ num_names++;
+ names = n;
+ }
+
+ bzero(&names[i],sizeof(names[i]));
+
+ return(i);
+}
+
+/****************************************************************************
+find a name
+****************************************************************************/
+static int find_name(char *s,int type,BOOL groups)
+{
+ int i;
+ time_t t = time(NULL);
+
+ for (i=0;i<num_names;i++)
+ if (names[i].valid && (groups || !ISGROUP(i)))
+ {
+ if ((names[i].ttl > 0) && (t > (names[i].start_time + names[i].ttl)))
+ names[i].valid = False;
+ else
+ {
+ if (name_equal(s,names[i].name,type,names[i].type)) {
+ return(i);
+ }
+ }
+ }
+ return -1;
+}
+
+
+/****************************************************************************
+check names, and change any 0 IPs to myip
+****************************************************************************/
+static void check_names(void)
+{
+ int i;
+ int group_count=0;
+
+ /* add the magic __SAMBA__ name */
+ add_host_name("__SAMBA__",0x20,&myip);
+ add_host_name("__SAMBA__",0x0,&myip);
+
+ for (i=0;i<num_names;i++)
+ if (names[i].valid) {
+ if (ISGROUP(i)) group_count++;
+ }
+
+ if (group_count == 0)
+ add_group_name(WORKGROUP);
+
+
+ for (i=0;i<num_names;i++)
+ if (names[i].valid && strequal((char *)inet_ntoa(names[i].ip),"0.0.0.0"))
+ names[i].ip = (ISGROUP(i)?bcast_ip:myip);
+}
+
+
+/****************************************************************************
+dump a copy of the name table
+****************************************************************************/
+static void dump_names(void)
+{
+ int i;
+ DEBUG(3,("Dump of local name table\n"));
+ for (i=0;i<num_names;i++)
+ if (names[i].valid) {
+ DEBUG(3,("%s %s %d %s",
+ names[i].name,inet_ntoa(names[i].ip),
+ names[i].ttl,BOOLSTR(names[i].isgroup)));
+ if (names[i].found_master)
+ DEBUG(3,(" %s",inet_ntoa(names[i].master_ip)));
+ DEBUG(3,("\n"));
+ }
+}
+
+
+/****************************************************************************
+load a netbios hosts file
+****************************************************************************/
+static void load_hosts_file(char *fname)
+{
+ int i;
+ FILE *f = fopen(fname,"r");
+ pstring line;
+ if (!f)
+ {
+ DEBUG(2,("Not using non-existant lmhosts file %s\n",fname));
+ return;
+ }
+
+ while (!feof(f))
+ {
+ if (!fgets_slash(line,sizeof(pstring),f)) continue;
+
+ if (*line == '#') continue;
+
+ {
+ string ip="",name="",flags="",extra="";
+ unsigned long a;
+ char *ptr;
+ int count = 0;
+ ptr = line;
+ if (next_token(&ptr,ip,NULL)) ++count;
+ if (next_token(&ptr,name,NULL)) ++count;
+ if (next_token(&ptr,flags,NULL)) ++count;
+ if (next_token(&ptr,extra,NULL)) ++count;
+
+ if (count <= 0) continue;
+
+ if (count > 0 && count < 2)
+ {
+ DEBUG(0,("Ill formed hosts line [%s]\n",line));
+ continue;
+ }
+
+ i = add_name();
+ if (i < 0)
+ {
+ fclose(f);
+ return;
+ }
+
+ a = interpret_addr(ip);
+ putip((char *)&names[i].ip,(char *)&a);
+
+ names[i].valid = True;
+ names[i].source = LMHOSTS;
+
+ StrnCpy(names[i].name,name,15);
+ if (strchr(flags,'G') || strchr(flags,'S'))
+ names[i].isgroup = True;
+ if (strchr(flags,'M') && !ISGROUP(i))
+ strcpy(myname,name);
+ if (strchr(flags,'U'))
+ names[i].unicast = True;
+ if (names[i].isgroup)
+ names[i].type = 0xF0; /* hopefully invalid */
+ else
+ names[i].type = 0x20;
+ }
+ }
+
+ fclose(f);
+}
+
+
+/****************************************************************************
+add a netbios group name
+****************************************************************************/
+static void add_group_name(char *name)
+{
+ int i = add_name();
+ if (i < 0)
+ return;
+
+ bzero((char *)&names[i].ip,sizeof(names[i].ip));
+
+ strcpy(names[i].name,name);
+ names[i].isgroup = True;
+ names[i].valid = True;
+ names[i].type = 0xF0;
+ names[i].source = SELF;
+}
+
+/****************************************************************************
+add a host name
+****************************************************************************/
+static void add_host_name(char *name,int type,struct in_addr *ip)
+{
+ int i;
+
+ if (find_name(name,type,True) >= 0) return;
+
+ i = add_name();
+ if (i < 0)
+ return;
+
+ names[i].ip = *ip;
+ strcpy(names[i].name,name);
+ names[i].valid = True;
+ names[i].start_time = time(NULL);
+ names[i].ttl = 0;
+ names[i].type = type;
+ names[i].source = SELF;
+}
+
+/****************************************************************************
+work out the length of a nmb message
+****************************************************************************/
+static int nmb_len(char *buf)
+{
+int i;
+int ret = 12;
+char *p = buf;
+int qdcount = RSVAL(buf,4);
+int ancount = RSVAL(buf,6);
+int nscount = RSVAL(buf,8);
+int arcount = RSVAL(buf,10);
+
+/* check for insane qdcount values? */
+if (qdcount > 100 || qdcount < 0)
+ {
+ DEBUG(6,("Invalid qdcount? qdcount=%d\n",qdcount));
+ return(0);
+ }
+
+for (i=0;i<qdcount;i++)
+ {
+ p = buf + ret;
+ ret += name_len(p) + 4;
+ }
+
+for (i=0;i<(ancount + nscount + arcount);i++)
+ {
+ int rdlength;
+ p = buf + ret;
+ ret += name_len(p) + 8;
+ p = buf + ret;
+ rdlength = RSVAL(p,0);
+ ret += rdlength + 2;
+ }
+
+return(ret);
+}
+
+/****************************************************************************
+receive a name message. timeout is in milliseconds
+****************************************************************************/
+static int receive_nmb(char *buffer,int timeout)
+{
+ int ret = read_max_udp(ClientNMB,buffer,sizeof(pstring),timeout);
+
+ if (ret < 0)
+ {
+ DEBUG(0,("No bytes from client\n"));
+ if (!is_daemon)
+ {
+ close_sockets();
+ exit(0);
+ }
+ }
+
+ if (ret <= 1)
+ return 0;
+
+ log_in(buffer,ret);
+
+ DEBUG(3,("received packet from (%s) nmb_len=%d len=%d\n",
+ inet_ntoa(lastip),nmb_len(buffer),ret));
+
+ return(ret);
+}
+
+/****************************************************************************
+send a name message
+****************************************************************************/
+static BOOL send_nmb(char *buf, int len, struct in_addr *ip,int port)
+{
+ BOOL ret;
+ struct sockaddr_in sock_out;
+
+ /* set the address and port */
+ bzero((char *)&sock_out,sizeof(sock_out));
+ putip((char *)&sock_out.sin_addr,(char *)ip);
+ sock_out.sin_port = htons( port );
+ sock_out.sin_family = AF_INET;
+
+ /* log the packet */
+ log_out(buf,len);
+
+ if (DEBUGLEVEL > 0)
+ DEBUG(3,("sending a packet of len %d to (%s) on port 137 of type DGRAM\n",
+ len,inet_ntoa(*ip)));
+
+ /* send it */
+ ret = (sendto(ClientNMB,buf,len,0,(struct sockaddr *)&sock_out,sizeof(sock_out)) >= 0);
+
+ if (!ret)
+ DEBUG(0,("Send packet failed. ERRNO=%d\n",errno));
+
+ return(ret);
+}
+
+/*******************************************************************
+check if an IP is on my net
+********************************************************************/
+static BOOL is_mynet(struct in_addr ip)
+{
+ unsigned int net1,net2,nmask,subnet1,subnet2;
+
+ nmask = *(unsigned int *)&Netmask;
+ net1 = (*(unsigned int *)&myip);
+ subnet1 = net1 & nmask;
+ net2 = (*(unsigned int *)&ip);
+ subnet2 = net2 & nmask;
+
+ return((net1 != net2) && (subnet1 == subnet2));
+}
+
+/****************************************************************************
+interpret a node status response
+****************************************************************************/
+static void interpret_node_status(char *inbuf, char *master)
+{
+ int level = master?3:0;
+ char *p = inbuf + 12 + name_len(inbuf+12) + 10;
+ int numnames = CVAL(p,0);
+ DEBUG(level,("received %d names\n",numnames));
+
+ p += 1;
+ while (numnames--)
+ {
+ char qname[17];
+ int type;
+ fstring flags="";
+ StrnCpy(qname,p,15);
+ type = CVAL(p,15);
+ p += 16;
+
+ if (p[0] & 0x80) strcat(flags,"<GROUP> ");
+ if (p[0] & 0x60 == 0) strcat(flags,"B ");
+ if (p[0] & 0x60 == 1) strcat(flags,"P ");
+ if (p[0] & 0x60 == 2) strcat(flags,"M ");
+ if (p[0] & 0x60 == 3) strcat(flags,"_ ");
+ if (p[0] & 0x10) strcat(flags,"<DEREGISTERING> ");
+ if (p[0] & 0x08) strcat(flags,"<CONFLICT> ");
+ if (p[0] & 0x04) strcat(flags,"<ACTIVE> ");
+ if (p[0] & 0x02) strcat(flags,"<PERMANENT> ");
+
+ if (master && type == 0x1d) {
+ StrnCpy(master,qname,15);
+ }
+
+ DEBUG(level,("\t%s (type=0x%x)\t%s\n",qname,type,flags));
+ p+=2;
+ }
+ DEBUG(level,("num_good_sends=%d num_good_receives=%d\n",
+ IVAL(p,20),IVAL(p,24)));
+}
+
+
+/****************************************************************************
+show a nmb message
+****************************************************************************/
+static void show_nmb(char *inbuf)
+{
+ int i,l;
+ int name_trn_id = RSVAL(inbuf,0);
+ int opcode = (CVAL(inbuf,2) >> 3) & 0xF;
+ int nm_flags = ((CVAL(inbuf,2) & 0x7) << 4) + (CVAL(inbuf,3)>>4);
+ int rcode = CVAL(inbuf,3) & 0xF;
+ int qdcount = RSVAL(inbuf,4);
+ int ancount = RSVAL(inbuf,6);
+ int nscount = RSVAL(inbuf,8);
+ int arcount = RSVAL(inbuf,10);
+ char name[100];
+
+ if (DEBUGLEVEL < 3) return;
+
+ DEBUG(3,("\nPACKET INTERPRETATION\n"));
+
+ if (opcode == 5 && ((nm_flags & ~1) == 0x10) && rcode == 0)
+ DEBUG(3,("NAME REGISTRATION REQUEST (%s)\n",nm_flags&1?"Broadcast":"Unicast"));
+
+ if (opcode == 5 && ((nm_flags & ~1) == 0x00) && rcode == 0)
+ DEBUG(3,("NAME OVERWRITE REQUEST AND DEMAND (%s)\n",nm_flags&1?"Broadcast":"Unicast"));
+
+ if (opcode == 9 && ((nm_flags & ~1) == 0x00) && rcode == 0)
+ DEBUG(3,("NAME REFRESH REQUEST (%s)\n",nm_flags&1?"Broadcast":"Unicast"));
+
+ if (opcode == 8)
+ DEBUG(3,("NAME REFRESH (%s)\n",nm_flags&1?"Broadcast":"Unicast"));
+
+ if (opcode == 5 && nm_flags == 0x58 && rcode == 0)
+ DEBUG(3,("POSITIVE NAME REGISTRATION RESPONSE\n"));
+
+ if (opcode == 5 && nm_flags == 0x58 && rcode != 0 && rcode != 7)
+ DEBUG(3,("NEGATIVE NAME REGISTRATION RESPONSE\n"));
+
+ if (opcode == 5 && nm_flags == 0x50 && rcode == 0)
+ DEBUG(3,("END-NODE CHALLENGE REGISTRATION RESPONSE\n"));
+
+ if (opcode == 5 && nm_flags == 0x58 && rcode != 0 && rcode == 7)
+ DEBUG(3,("NAME CONFLICT DEMAND\n"));
+
+ if (opcode == 6 && (nm_flags&~1) == 0x00 && rcode == 0)
+ DEBUG(3,("NAME RELEASE REQUEST & DEMAND (%s)\n",nm_flags&1?"Broadcast":"Unicast"));
+
+ if (opcode == 6 && (nm_flags&~1) == 0x40 && rcode == 0)
+ DEBUG(3,("POSITIVE NAME RELEASE RESPONSE\n"));
+
+ if (opcode == 6 && (nm_flags&~1) == 0x40 && rcode != 0)
+ DEBUG(3,("NEGATIVE NAME RELEASE RESPONSE\n"));
+
+ if (opcode == 0 && (nm_flags&~1) == 0x10 && rcode == 0)
+ DEBUG(3,("NAME QUERY REQUEST (%s)\n",nm_flags&1?"Broadcast":"Unicast"));
+
+ if (opcode == 0 && (nm_flags&~0x28) == 0x50 && rcode == 0)
+ DEBUG(3,("POSITIVE NAME QUERY RESPONSE\n"));
+
+ if (opcode == 0 && (nm_flags&~0x08) == 0x50 && rcode != 0)
+ DEBUG(3,("NEGATIVE NAME QUERY RESPONSE\n"));
+
+ if (opcode == 0 && nm_flags == 0x10 && rcode == 0)
+ DEBUG(3,("REDIRECT NAME QUERY RESPONSE\n"));
+
+ if (opcode == 7 && nm_flags == 0x80 && rcode == 0)
+ DEBUG(3,("WAIT FOR ACKNOWLEDGEMENT RESPONSE\n"));
+
+ if (opcode == 0 && (nm_flags&~1) == 0x00 && rcode == 0)
+ DEBUG(3,("NODE STATUS REQUEST (%s)\n",nm_flags&1?"Broadcast":"Unicast"));
+
+ if (opcode == 0 && nm_flags == 0x40 && rcode == 0)
+ {
+ DEBUG(3,("NODE STATUS RESPONSE\n"));
+ interpret_node_status(inbuf,NULL);
+ }
+
+
+ DEBUG(3,("name_trn_id=0x%x\nopcode=0x%x\nnm_flags=0x%x\nrcode=0x%x\n",
+ name_trn_id,opcode,nm_flags,rcode));
+ DEBUG(3,("qdcount=%d\nancount=%d\nnscount=%d\narcount=%d\n",
+ qdcount,ancount,nscount,arcount));
+
+ l = 12;
+ for (i=0;i<qdcount;i++)
+ {
+ int type,class;
+ DEBUG(3,("QUESTION %d\n",i));
+ name_extract(inbuf,l,name);
+ l += name_len(inbuf+l);
+ type = RSVAL(inbuf+l,0);
+ class = RSVAL(inbuf+l,2);
+ l += 4;
+ DEBUG(3,("\t%s\n\ttype=0x%x\n\tclass=0x%x\n",name,type,class));
+ }
+
+ for (i=0;i<(ancount + nscount + arcount);i++)
+ {
+ int type,class,ttl,rdlength;
+ DEBUG(3,("RESOURCE %d\n",i));
+ name_extract(inbuf,l,name);
+ l += name_len(inbuf + l);
+ type = RSVAL(inbuf+l,0);
+ class = RSVAL(inbuf+l,2);
+ ttl = RIVAL(inbuf+l,4);
+ rdlength = RSVAL(inbuf+l,8);
+ l += 10 + rdlength;
+ DEBUG(3,("\t%s\n\ttype=0x%x\n\tclass=0x%x\n",name,type,class));
+ DEBUG(3,("\tttl=%d\n\trdlength=%d\n",ttl,rdlength));
+ }
+
+ DEBUG(3,("\n"));
+
+}
+
+
+/****************************************************************************
+do a netbios name status to a host
+****************************************************************************/
+static BOOL name_status(char *name,int type,struct in_addr to_ip,char *master)
+{
+ pstring inbuf,outbuf;
+ static uint16 name_trn_id = 0x4262;
+ char *p;
+ int retries = 2;
+ int retry_time = 5000;
+ struct timeval tval;
+
+ bzero(inbuf,sizeof(inbuf));
+ bzero(outbuf,sizeof(outbuf));
+
+ name_trn_id += getpid() % 100;
+ name_trn_id = (name_trn_id % 10000);
+
+ RSSVAL(outbuf,0,name_trn_id);
+ CVAL(outbuf,2) = 0;
+ CVAL(outbuf,3) = 0x0;
+ RSSVAL(outbuf,4,1);
+ RSSVAL(outbuf,6,0);
+ RSSVAL(outbuf,8,0);
+ RSSVAL(outbuf,10,0);
+ p = outbuf+12;
+ name_mangle(name,p,type);
+ p += name_len(p);
+ RSSVAL(p,0,0x21);
+ RSSVAL(p,2,0x1);
+ p += 4;
+
+ show_nmb(outbuf);
+
+ GetTimeOfDay(&tval);
+
+ if (!send_nmb(outbuf,nmb_len(outbuf), &to_ip, NMB_PORT))
+ return False;
+
+ while (1)
+ {
+ struct timeval tval2;
+ GetTimeOfDay(&tval2);
+ if (TvalDiff(&tval,&tval2) > retry_time) {
+ if (!retries) break;
+ if (!send_nmb(outbuf,nmb_len(outbuf), &to_ip, NMB_PORT))
+ return False;
+ GetTimeOfDay(&tval);
+ retries--;
+ }
+
+ if (receive_nmb(inbuf,90))
+ {
+ int rec_name_trn_id = RSVAL(inbuf,0);
+ int rcode = CVAL(inbuf,3) & 0xF;
+ int response = (CVAL(inbuf,2)>>7);
+ int qdcount = RSVAL(inbuf,4);
+ int ancount = RSVAL(inbuf,6);
+
+ show_nmb(inbuf);
+
+ /* is it a positive response to our request? */
+ if (response && (rec_name_trn_id == name_trn_id)) {
+ if (rcode==0 && ancount==1 && qdcount==0) {
+ interpret_node_status(inbuf, master);
+ return(True);
+ }
+ return(False);
+ }
+ }
+ }
+
+ DEBUG(0,("No status response (this is not unusual)\n"));
+
+ return(False);
+}
+
+/****************************************************************************
+construct a host announcement unicast
+****************************************************************************/
+static BOOL send_udp_dgram(char *buf,int len,
+ char *srcname,char *dstname,
+ int src_type,int dest_type,
+ struct in_addr dest_ip)
+{
+ pstring outbuf;
+ char *p,*p2;
+ static int id=0;
+ char tmp[4];
+ struct sockaddr_in sock_out;
+
+ bzero(outbuf,sizeof(outbuf));
+ RSSVAL(outbuf,0,0x1102); /* what is this? */
+ RSSVAL(outbuf,2,++id);
+ putip(outbuf+4,(void *)&myip);
+ RSSVAL(outbuf,8,DGRAM_PORT);
+ RSSVAL(outbuf,12,0);
+ p = outbuf + 14;
+ p += name_mangle(srcname,p,src_type);
+ p += name_mangle(dstname,p,dest_type);
+
+ /* now setup the smb part */
+ p -= 4;
+ memcpy(tmp,p,4);
+ set_message(p,17,17 + len,True);
+ memcpy(p,tmp,4);
+
+ CVAL(p,smb_com) = SMBtrans;
+ SSVAL(p,smb_vwv1,len);
+ SSVAL(p,smb_vwv11,len);
+ SSVAL(p,smb_vwv12,86);
+ SSVAL(p,smb_vwv13,3);
+ SSVAL(p,smb_vwv14,1);
+ SSVAL(p,smb_vwv15,1);
+ SSVAL(p,smb_vwv16,2);
+ p2 = smb_buf(p);
+ strcpy(p2,"\\MAILSLOT\\BROWSE");
+ p2 = skip_string(p2,1);
+
+ memcpy(p2,buf,len);
+ p2 += len;
+
+ len = PTR_DIFF(p2,outbuf);
+ RSSVAL(outbuf,10,len);
+
+
+ /* set the address and port */
+ bzero((char *)&sock_out,sizeof(sock_out));
+ putip((char *)&sock_out.sin_addr,(char *)&dest_ip);
+ sock_out.sin_port = htons(DGRAM_PORT);
+ sock_out.sin_family = AF_INET;
+
+ /* log the packet */
+ log_out(outbuf,len);
+
+ /* send it */
+ if (sendto(ClientDGRAM,outbuf,len,0,
+ (struct sockaddr *)&sock_out,sizeof(sock_out)) < 0) {
+ DEBUG(3,("Sendto failed errno=%d (%s)\n",errno,strerror(errno)));
+ return(False);
+ }
+
+ return(True);
+}
+
+/****************************************************************************
+construct a host announcement unicast
+****************************************************************************/
+static void announce_host(int i,char *my_name,char *Comment)
+{
+ static int announce_interval = 1;
+ char *group = names[i].name;
+ struct in_addr dest_ip = names[i].ip;
+ pstring outbuf;
+ char *p;
+
+ names[i].count++;
+
+ if ((names[i].count % announce_interval) != 0) return;
+
+ if (announce_interval < 2) announce_interval++;
+
+ DEBUG(2,("Sending host announcement to %s for group %s\n",
+ inet_ntoa(dest_ip),group));
+
+ if (!*Comment) Comment = "NoComment";
+ if (!*my_name) my_name = "NoName";
+ if (!*group) group = "NoGroup";
+
+ if (strlen(Comment) > 47) Comment[47] = 0;
+
+ bzero(outbuf,sizeof(outbuf));
+ p = outbuf;
+ CVAL(p,0) = 1; /* host announce */
+ SSVAL(p,1,0x6006); /* update count?? */
+ CVAL(p,3) = 0xEA; /* res1 */
+ SSVAL(p,4,announce_interval);
+ p += 6;
+ StrnCpy(p,my_name,16);
+ strupper(p);
+ p += 16;
+ CVAL(p,0) = 1; /* major version (was 1) */
+ CVAL(p,1) = 0x33; /* minor version (was 51) */
+ SIVAL(p,2,0xB03); /* server and w'station + unix + printq + domain member*/
+ SSVAL(p,6,0x30B); /* election version */
+ SSVAL(p,8,0xAA55); /* browse constant */
+ p += 10;
+ strcpy(p,Comment);
+ p += strlen(p)+1;
+
+ send_udp_dgram(outbuf,PTR_DIFF(p,outbuf),my_name,group,0,0x1d,dest_ip);
+}
+
+
+
+/****************************************************************************
+send a name registration packet
+****************************************************************************/
+static void send_registration(char *name,int name_type,struct in_addr dest_ip,struct in_addr ip,BOOL refresh,int ttl)
+{
+ char *p;
+ static int t = 0x176;
+ pstring outbuf;
+ bzero(outbuf,sizeof(outbuf));
+ /* send a registration request */
+ RSSVAL(outbuf,0,t++);
+ if (refresh)
+ CVAL(outbuf,2) = (0<<7) | (9<<3) | 0;
+ else
+ CVAL(outbuf,2) = (0<<7) | (5<<3) | 1;
+
+ CVAL(outbuf,3) = (1<<4);
+ RSSVAL(outbuf,4,1);
+ RSSVAL(outbuf,6,0);
+ RSSVAL(outbuf,8,0);
+ RSSVAL(outbuf,10,1);
+ p = outbuf+12;
+ name_mangle(name,p,name_type);
+ p += name_len(p);
+ RSSVAL(p,0,0x20);
+ RSSVAL(p,2,0x1);
+ p += 4;
+ RSSVAL(p,0,12);
+ CVAL(p,0) = CVAL(p,0) | 0xC0;
+ p += 2;
+ RSSVAL(p,0,0x20);
+ RSSVAL(p,2,0x1);
+ p += 4;
+ RSIVAL(p,0,ttl);
+
+ RSSVAL(p,4,6);
+ RSSVAL(p,6,0);
+ p += 8;
+ putip(p,&ip);
+ p += 4;
+
+ DEBUG(2,("Sending a name registration request\n"));
+ if (DEBUGLEVEL > 2)
+ show_nmb(outbuf);
+
+ send_nmb(outbuf,PTR_DIFF(p,outbuf),&dest_ip,NMB_PORT);
+}
+
+/*******************************************************************
+find a master browser
+********************************************************************/
+BOOL find_master(char *name1,struct in_addr ip,struct in_addr *ipout)
+{
+ int type = 0x1d;
+ fstring name;
+ BOOL ret;
+ strcpy(name,name1);
+ if (strequal(name,"*")) {
+ strcpy(name,"\001\002__MSBROWSE__\002");
+ type = 1;
+ }
+ ret = name_query(name,type,True,False,ip,ipout);
+ if (!ret) return(False);
+ if (type != 1) return(True);
+
+ name_status(name,type,*ipout,name1);
+ return(name1[0] != '*');
+}
+
+/****************************************************************************
+process a workgroup announce frame
+****************************************************************************/
+static void process_workgroup_announce(char *group,struct in_addr ip)
+{
+ int i;
+ for (i=0;i<num_names;i++)
+ if (names[i].valid) {
+ if (names[i].name[0] == '*') {
+ StrnCpy(names[i].name,group,15);
+ names[i].master_ip = ip;
+ names[i].found_master = True;
+ names[i].count=0;
+ announce_host(i,myname,comment);
+ return;
+ }
+ if (names[i].isgroup && name_equal(names[i].name,group,0,0)) {
+ int j;
+ for (j=i;j<num_names;j++)
+ if (names[j].valid && names[j].isgroup && names[i].found_master &&
+ name_equal(names[i].name,group,0,0)) return;
+ names[i].master_ip = ip;
+ names[i].found_master = True;
+ names[i].count=0;
+ announce_host(i,myname,comment);
+ return;
+ }
+ }
+}
+
+
+/****************************************************************************
+process a browse frame
+****************************************************************************/
+static void process_browse_packet(char *buf,int len)
+{
+ char *p;
+ int command = CVAL(buf,0);
+ switch (command) {
+ case 0xc: /* workgroup announcement */
+ {
+ fstring group;
+ p = buf + 6;
+ StrnCpy(group,p,15);
+ DEBUG(2,("Got workgroup announce for %s (%s)\n",
+ group,inet_ntoa(lastip)));
+ process_workgroup_announce(group,lastip);
+ break;
+ }
+ }
+
+}
+
+/****************************************************************************
+process udp 138 datagrams
+****************************************************************************/
+static void process_dgram(void)
+{
+ pstring inbuf;
+ int len;
+ while (read_max_udp(ClientDGRAM,inbuf,sizeof(inbuf),1) > 4) {
+ char *p = inbuf;
+ len = RSVAL(inbuf,10);
+ p += 14;
+ p += name_len(p);
+ p += name_len(p);
+ p -= 4;
+ if (CVAL(p,smb_com) != SMBtrans) continue;
+ if (!strequal(smb_buf(p),"\\MAILSLOT\\BROWSE")) continue;
+ len = SVAL(p,smb_vwv11);
+ p = smb_base(p) + SVAL(p,smb_vwv12);
+ if (len <= 0) continue;
+ process_browse_packet(p,len);
+ }
+}
+
+/****************************************************************************
+a hook for registration of my own names
+****************************************************************************/
+static void do_registration_hook(void)
+{
+ static int count = 0;
+ static time_t last_t=0;
+ time_t t = time(NULL);
+
+ if (last_t && (t-last_t)<REGISTRATION_INTERVAL) return;
+ last_t = t;
+
+ send_registration(myname,0x20,bcast_ip,myip,count>0,300000);
+ count++;
+}
+
+/****************************************************************************
+a hook for browsing handling - called every BROWSE_INTERVAL secs
+****************************************************************************/
+static void do_browse_hook(void)
+{
+ static BOOL first = True;
+ int i;
+ static time_t last_t=0;
+ time_t t = time(NULL);
+
+ if (last_t && (t-last_t)<browse_interval) return;
+ last_t = t;
+
+ for (i=0;i<num_names;i++)
+ {
+ BOOL old_found_master = names[i].found_master;
+
+ if (!NAMEVALID(i) || !ISGROUP(i)) continue;
+
+ if (names[i].found_master) {
+ struct in_addr ip2;
+ announce_host(i,myname,comment);
+
+ if (!name_query(names[i].name,0x1d,True,False,
+ names[i].master_ip,
+ &ip2)) {
+ DEBUG(2,("%s Master browser at %s failed to respond\n",
+ timestring(),
+ inet_ntoa(names[i].master_ip)));
+ names[i].found_master = False;
+ } else {
+ names[i].master_ip = ip2;
+ }
+ }
+
+ if (!names[i].found_master) {
+ struct in_addr ip2;
+ names[i].found_master = find_master(names[i].name,names[i].ip,&ip2);
+
+ if (names[i].found_master) {
+ names[i].master_ip = ip2;
+ DEBUG(1,("%s New master browser for %s at %s\n",
+ timestring(),
+ names[i].name,inet_ntoa(names[i].master_ip)));
+ names[i].count = 0;
+ announce_host(i,myname,comment);
+ }
+ }
+
+ if (!names[i].found_master) {
+ int level = (old_found_master||first)?1:2;
+ DEBUG(level,("%s Failed to find a master browser for %s using %s\n",
+ timestring(),
+ names[i].name,inet_ntoa(names[i].ip)));
+ }
+ }
+ first = False;
+}
+
+
+/****************************************************************************
+ do a netbios name query to find someones IP
+ ****************************************************************************/
+static BOOL name_query(char *name,int name_type, BOOL bcast,BOOL recurse,
+ struct in_addr to_ip, struct in_addr *ip)
+{
+ BOOL found=False;
+ static uint16 name_trn_id = 0;
+ int retries = 3;
+ int retry_time = bcast?250:5000;
+ struct timeval tval;
+ struct packet_struct p;
+ struct packet_struct *p2;
+ struct nmb_packet *nmb = &p.packet.nmb;
+
+ bzero((char *)&p,sizeof(p));
+
+ if (!name_trn_id) name_trn_id = (time(NULL)%0x7FFF) + (getpid()%100);
+ name_trn_id = (name_trn_id+1) % 0x7FFF;
+
+ nmb->header.name_trn_id = name_trn_id;
+ nmb->header.opcode = 0;
+ nmb->header.response = False;
+ nmb->header.nm_flags.bcast = bcast;
+ nmb->header.nm_flags.recursion_available = CanRecurse;
+ nmb->header.nm_flags.recursion_desired = recurse;
+ nmb->header.nm_flags.trunc = False;
+ nmb->header.nm_flags.authoritative = False;
+ nmb->header.rcode = 0;
+ nmb->header.qdcount = 1;
+ nmb->header.ancount = 0;
+ nmb->header.nscount = 0;
+ nmb->header.arcount = 0;
+
+ strcpy(nmb->question.question_name.name,name);
+ strupper(nmb->question.question_name.name);
+ nmb->question.question_name.name_type = name_type;
+ strcpy(nmb->question.question_name.scope,scope);
+
+ nmb->question.question_type = 0x20;
+ nmb->question.question_class = 0x1;
+
+ p.ip = to_ip;
+ p.port = NMB_PORT;
+ p.fd = ClientNMB;
+ p.timestamp = time(NULL);
+ p.packet_type = NMB_PACKET;
+
+ GetTimeOfDay(&tval);
+
+ if (!send_packet(&p))
+ return(False);
+
+ retries--;
+
+ while (1)
+ {
+ struct timeval tval2;
+ GetTimeOfDay(&tval2);
+ if (TvalDiff(&tval,&tval2) > retry_time) {
+ if (!retries) break;
+ if (!found && !send_packet(&p))
+ return False;
+ GetTimeOfDay(&tval);
+ retries--;
+ }
+
+ if ((p2=receive_packet(ClientNMB,NMB_PACKET,90)))
+ {
+ struct nmb_packet *nmb2 = &p2->packet.nmb;
+ if (nmb->header.name_trn_id != nmb2->header.name_trn_id ||
+ !nmb2->header.response) {
+ /* its not for us - deal with it later */
+ queue_packet(p2);
+ continue;
+ }
+
+ if (nmb2->header.opcode != 0 ||
+ nmb2->header.nm_flags.bcast ||
+ nmb2->header.rcode ||
+ !nmb2->header.ancount) {
+ /* XXXX what do we do with this? could be a redirect, but
+ we'll discard it for the moment */
+ free_packet(p2);
+ continue;
+ }
+
+ putip((char *)ip,&nmb2->answers->rdata[2]);
+ DEBUG(2,("Got a positive name query response from %s",
+ inet_ntoa(p2->ip)));
+ DEBUG(2,(" (%s)\n",inet_ntoa(*ip)));
+ found=True; retries=0;
+ }
+ }
+
+ return(found);
+}
+
+
+/****************************************************************************
+reply to a name release
+****************************************************************************/
+static void reply_name_release(struct packet_struct *p)
+{
+ struct nmb_packet *nmb = &p->packet.nmb;
+ char *qname = nmb->question.question_name.name;
+ BOOL wildcard = (qname[0] == '*');
+ int name_type = nmb->question.question_name.name_type;
+ int nb_flags = nmb->additional->rdata[0];
+ struct packet_struct p2;
+ struct nmb_packet *nmb2;
+ struct res_rec answer_rec;
+ struct in_addr ip;
+ BOOL release_ok=False;
+ int reason=5;
+ int n;
+
+ if (wildcard) return;
+
+ putip((char *)&ip,&nmb->additional->rdata[2]);
+
+ n = find_name(qname,name_type,True);
+ if (n>=0 && names[n].source == REGISTER &&
+ !memcmp((char *)&ip,(char *)&names[n].ip,sizeof(ip))) {
+ release_ok = True;
+ names[n].valid = False;
+ }
+
+ /* Send a POSITIVE NAME RELEASE RESPONSE */
+ p2 = *p;
+ nmb2 = &p2.packet.nmb;
+
+ nmb2->header.response = True;
+ nmb2->header.nm_flags.bcast = False;
+ nmb2->header.nm_flags.recursion_available = CanRecurse;
+ nmb2->header.nm_flags.trunc = False;
+ nmb2->header.nm_flags.authoritative = True;
+ nmb2->header.qdcount = 0;
+ nmb2->header.ancount = 1;
+ nmb2->header.nscount = 0;
+ nmb2->header.arcount = 0;
+ nmb2->header.rcode = release_ok?0:reason;
+
+ nmb2->answers = &answer_rec;
+ bzero((char *)nmb2->answers,sizeof(*nmb2->answers));
+
+ nmb2->answers->rr_name = nmb->question.question_name;
+ nmb2->answers->rr_type = nmb->question.question_type;
+ nmb2->answers->rr_class = nmb->question.question_class;
+ nmb2->answers->ttl = 0;
+ nmb2->answers->rdlength = 6;
+ nmb2->answers->rdata[0] = nb_flags;
+ putip(&nmb2->answers->rdata[2],(char *)&ip);
+
+ send_packet(&p2);
+}
+
+
+
+/****************************************************************************
+ reply to a reg request
+ **************************************************************************/
+static void reply_name_reg(struct packet_struct *p)
+{
+ struct nmb_packet *nmb = &p->packet.nmb;
+ char *qname = nmb->question.question_name.name;
+ BOOL wildcard = (qname[0] == '*');
+ BOOL bcast = nmb->header.nm_flags.bcast;
+ int name_type = nmb->question.question_name.name_type;
+ int ttl = nmb->additional->ttl;
+ int nb_flags = nmb->additional->rdata[0];
+ struct packet_struct p2;
+ struct nmb_packet *nmb2;
+ struct res_rec answer_rec;
+ struct in_addr ip;
+
+ if (wildcard) return;
+
+ putip((char *)&ip,&nmb->additional->rdata[2]);
+
+ if ((nb_flags&0x80) == 0 && (name_type != 0x1d)) {
+ int n = find_name(qname,name_type,True);
+ if (ttl==0) ttl = NMBD_MAX_TTL;
+ ttl = MIN(ttl,NMBD_MAX_TTL);
+
+ if (n>=0 && names[n].source != REGISTER && names[n].source != DNS)
+ return;
+
+ if (n<0)
+ n = add_name();
+ if (n<0) return;
+
+ bzero(&names[n],sizeof(names[n]));
+
+ StrnCpy(names[n].name,qname,15);
+ names[n].type = name_type;
+ names[n].unicast = !dns_serve || is_mynet(ip);
+ names[n].ip = ip;
+ names[n].valid = True;
+ names[n].ttl = ttl;
+ names[n].source = REGISTER;
+ names[n].start_time = p->timestamp;
+ }
+
+ if (bcast) return;
+
+ /* Send a POSITIVE NAME REGISTRATION RESPONSE */
+ /* a lot of fields get copied from the query. This gives us the IP
+ and port the reply will be sent to etc */
+ p2 = *p;
+ nmb2 = &p2.packet.nmb;
+
+ nmb2->header.response = True;
+ nmb2->header.nm_flags.bcast = False;
+ nmb2->header.nm_flags.recursion_available = CanRecurse;
+ nmb2->header.nm_flags.trunc = False;
+ nmb2->header.nm_flags.authoritative = True;
+ nmb2->header.qdcount = 0;
+ nmb2->header.ancount = 1;
+ nmb2->header.nscount = 0;
+ nmb2->header.arcount = 0;
+
+ nmb2->answers = &answer_rec;
+ bzero((char *)nmb2->answers,sizeof(*nmb2->answers));
+
+ nmb2->answers->rr_name = nmb->question.question_name;
+ nmb2->answers->rr_type = nmb->question.question_type;
+ nmb2->answers->rr_class = nmb->question.question_class;
+
+ /* we want them to refresh in case we die */
+ if (!ttl) ttl = 15*60;
+ ttl = MIN(ttl,15*60);
+
+ nmb2->answers->ttl = ttl;
+ nmb2->answers->rdlength = 6;
+ nmb2->answers->rdata[0] = nb_flags;
+ putip(&nmb2->answers->rdata[2],(char *)&ip);
+
+ send_packet(&p2);
+}
+
+
+/****************************************************************************
+reply to a name status query
+****************************************************************************/
+static void reply_name_status(struct packet_struct *p)
+{
+ struct nmb_packet *nmb = &p->packet.nmb;
+ char *qname = nmb->question.question_name.name;
+ BOOL wildcard = (qname[0] == '*');
+ int name_type = nmb->question.question_name.name_type;
+ struct packet_struct p2;
+ struct nmb_packet *nmb2;
+ struct res_rec answer_rec;
+ char *buf;
+ int count,i;
+
+ if (!wildcard) {
+ i = find_name(qname,name_type,False);
+
+ if (i < 0)
+ return;
+ if (names[i].source != SELF && names[i].source != LMHOSTS)
+ return;
+ }
+
+ /* Send a POSITIVE NAME STATUS RESPONSE */
+ /* a lot of fields get copied from the query. This gives us the IP
+ and port the reply will be sent to etc */
+ p2 = *p;
+ nmb2 = &p2.packet.nmb;
+
+ nmb2->header.response = True;
+ nmb2->header.nm_flags.bcast = False;
+ nmb2->header.nm_flags.recursion_available = CanRecurse;
+ nmb2->header.nm_flags.trunc = False;
+ nmb2->header.nm_flags.authoritative = True; /* WfWg ignores
+ non-authoritative answers */
+ nmb2->header.qdcount = 0;
+ nmb2->header.ancount = 1;
+ nmb2->header.nscount = 0;
+ nmb2->header.arcount = 0;
+
+ nmb2->answers = &answer_rec;
+ bzero((char *)nmb2->answers,sizeof(*nmb2->answers));
+
+
+ nmb2->answers->rr_name = nmb->question.question_name;
+ nmb2->answers->rr_type = nmb->question.question_type;
+ nmb2->answers->rr_class = nmb->question.question_class;
+ nmb2->answers->ttl = 0; /* XXX what ttl to answer with? */
+
+ for (count=0,i=0;i<num_names;i++)
+ if (names[i].valid) count++;
+ count = MIN(count,400/18); /* XXXX hack, we should calculate exactly
+ how many will fit */
+
+
+ buf = &nmb2->answers->rdata[0];
+ SCVAL(buf,0,count);
+ buf += 1;
+
+ for (i=0;i<num_names && count>0;i++)
+ if (names[i].valid)
+ {
+ bzero(buf,18);
+ strcpy(buf,names[i].name);
+ strupper(buf);
+ buf[15] = names[i].type;
+ buf += 16;
+ buf[0] = 0x4; /* active */
+ if (strequal(names[i].name,myname)) buf[0] |= 0x2; /* permanent */
+ if (ISGROUP(i)) buf[0] |= 0x80; /* group */
+ buf += 2;
+ count--;
+ }
+
+ /* we should fill in more fields of the statistics structure */
+ bzero(buf,46);
+ putip(buf,(char *)&myip);
+ {
+ extern int num_good_sends,num_good_receives;
+ SIVAL(buf,20,num_good_sends);
+ SIVAL(buf,24,num_good_receives);
+ }
+
+ buf += 46;
+
+ nmb2->answers->rdlength = PTR_DIFF(buf,&nmb2->answers->rdata[0]);
+
+ send_packet(&p2);
+}
+
+
+
+/****************************************************************************
+reply to a name query
+****************************************************************************/
+static void reply_name_query(struct packet_struct *p)
+{
+ struct nmb_packet *nmb = &p->packet.nmb;
+ char *qname = nmb->question.question_name.name;
+ BOOL wildcard = (qname[0] == '*');
+ BOOL bcast = nmb->header.nm_flags.bcast;
+ struct in_addr retip;
+ int name_type = nmb->question.question_name.name_type;
+ struct packet_struct p2;
+ struct nmb_packet *nmb2;
+ struct res_rec answer_rec;
+
+ if (!wildcard) {
+ int i = find_name(qname,name_type,False);
+
+ if (i < 0)
+ i = find_name(qname,name_type,True);
+
+ if (i >= 0)
+ {
+ if (bcast && (names[i].unicast || names[i].source == REGISTER))
+ return;
+
+ if (ISGROUP(i))
+ return;
+
+ retip = names[i].ip;
+ }
+ else
+ {
+ if ((name_type!=0 && name_type!=0x3 && name_type!=0x20) ||
+ (bcast && !dns_serve)) {
+ return;
+ } else {
+ unsigned long a;
+
+ a = interpret_addr(qname);
+ if (!a) return;
+
+ /* here is where we might recurse */
+ putip((char *)&retip,(char *)&a);
+
+ if (bcast && is_mynet(retip))
+ return;
+
+ i = find_name(qname,name_type,True);
+ if (i < 0) {
+ if ((i=add_name())>=0) {
+ StrnCpy(names[i].name,qname,15);
+ names[i].type = name_type;
+ names[i].unicast = is_mynet(retip);
+ names[i].ip = retip;
+ names[i].valid = True;
+ names[i].ttl = 120; /* give it two minutes */
+ names[i].start_time = p->timestamp;
+ names[i].source = DNS;
+ }
+ }
+ }
+ DEBUG(2,(" sending positive reply (%s)\n",inet_ntoa(retip)));
+ }
+ } else {
+ retip = myip;
+ }
+
+
+ /* a lot of fields get copied from the query. This gives us the IP
+ and port the reply will be sent to etc */
+ p2 = *p;
+ nmb2 = &p2.packet.nmb;
+
+ nmb2->header.response = True;
+ nmb2->header.nm_flags.bcast = False;
+ nmb2->header.nm_flags.recursion_available = CanRecurse;
+ nmb2->header.nm_flags.trunc = False;
+ nmb2->header.nm_flags.authoritative = True; /* WfWg ignores
+ non-authoritative answers */
+ nmb2->header.qdcount = 0;
+ nmb2->header.ancount = 1;
+ nmb2->header.nscount = 0;
+ nmb2->header.arcount = 0;
+
+ nmb2->answers = &answer_rec;
+ bzero((char *)nmb2->answers,sizeof(*nmb2->answers));
+
+ nmb2->answers->rr_name = nmb->question.question_name;
+ nmb2->answers->rr_type = nmb->question.question_type;
+ nmb2->answers->rr_class = nmb->question.question_class;
+ nmb2->answers->ttl = 0; /* XXX what ttl to answer with? */
+ nmb2->answers->rdlength = 6;
+ nmb2->answers->rdata[0] = 0; /* XXXX nbflags - what should this be? */
+ nmb2->answers->rdata[1] = 0;
+ putip(&nmb2->answers->rdata[2],(char *)&retip);
+
+ send_packet(&p2);
+}
+
+
+
+/* the global packet linked-list. incoming entries are added to the
+ end of this list. it is supposed to remain fairly short so we
+ won't bother with an end pointer. */
+static struct packet_struct *packet_queue = NULL;
+
+
+/*******************************************************************
+ queue a packet into the packet queue
+ ******************************************************************/
+static void queue_packet(struct packet_struct *packet)
+{
+ struct packet_struct *p;
+ if (!packet_queue) {
+ packet->prev = NULL;
+ packet->next = NULL;
+ packet_queue = packet;
+ return;
+ }
+
+ /* find the bottom */
+ for (p=packet_queue;p->next;p=p->next) ;
+
+ p->next = packet;
+ packet->next = NULL;
+ packet->prev = p;
+}
+
+/****************************************************************************
+ process a nmb packet
+ ****************************************************************************/
+static void process_nmb(struct packet_struct *p)
+{
+ struct nmb_packet *nmb = &p->packet.nmb;
+
+ /* if this is a response then ignore it */
+ if (nmb->header.response) return;
+
+ if (!nmb->header.nm_flags.bcast &&
+ nmb->header.opcode == 0x5 &&
+ nmb->header.qdcount==1 &&
+ nmb->header.arcount==1)
+ {
+ reply_name_reg(p);
+ return;
+ }
+
+ if (nmb->header.opcode==0 &&
+ nmb->header.qdcount==1)
+ {
+ switch (nmb->question.question_type)
+ {
+ case 0x20:
+ reply_name_query(p);
+ break;
+
+ case 0x21:
+ reply_name_status(p);
+ break;
+ }
+ return;
+ }
+
+ if (!nmb->header.nm_flags.bcast &&
+ nmb->header.opcode == 6 &&
+ nmb->header.qdcount==1 &&
+ nmb->header.arcount==1)
+ {
+ reply_name_release(p);
+ return;
+ }
+
+ if (!nmb->header.nm_flags.bcast &&
+ ((nmb->header.opcode == 8) || (nmb->header.opcode == 9)) &&
+ nmb->header.qdcount==1 &&
+ nmb->header.arcount==1)
+ {
+ reply_name_reg(p);
+ return;
+ }
+}
+
+
+
+/*******************************************************************
+ run elements off the packet queue till its empty
+ ******************************************************************/
+static void run_packet_queue(void)
+{
+ struct packet_struct *p;
+
+ while ((p=packet_queue)) {
+ switch (p->packet_type)
+ {
+ case NMB_PACKET:
+ process_nmb(p);
+ break;
+
+ case DGRAM_PACKET:
+ /* process_dgram(p); */
+ break;
+ }
+
+ packet_queue = packet_queue->next;
+ if (packet_queue) packet_queue->prev = NULL;
+ free_packet(p);
+ }
+}
+
+
+/****************************************************************************
+ The main select loop, listen for packets and respond
+ ***************************************************************************/
+void process(void)
+{
+ while (True)
+ {
+ fd_set fds;
+ int selrtn;
+ struct timeval timeout;
+
+ do_registration_hook();
+ do_browse_hook();
+
+ FD_ZERO(&fds);
+ FD_SET(ClientNMB,&fds);
+ FD_SET(ClientDGRAM,&fds);
+ timeout.tv_sec = NMBD_SELECT_LOOP;
+ timeout.tv_usec = 0;
+
+ selrtn = sys_select(&fds,&timeout);
+
+ if (FD_ISSET(ClientNMB,&fds)) {
+ struct packet_struct *packet = read_packet(ClientNMB,NMB_PACKET);
+ if (packet) queue_packet(packet);
+ }
+
+ if (FD_ISSET(ClientDGRAM,&fds)) {
+ struct packet_struct *packet = read_packet(ClientDGRAM,DGRAM_PACKET);
+ if (packet) queue_packet(packet);
+ }
+
+ run_packet_queue();
+ }
+}
+
+
+/****************************************************************************
+ open the socket communication
+****************************************************************************/
+static BOOL open_sockets(BOOL isdaemon,int port)
+{
+ struct hostent *hp;
+
+ /* get host info */
+ if ((hp = Get_Hostbyname(myhostname)) == 0)
+ {
+ DEBUG(0,( "Get_Hostbyname: Unknown host. %s\n",myhostname));
+ return False;
+ }
+
+ if (isdaemon)
+ ClientNMB = open_socket_in(SOCK_DGRAM, port,*lookup?3:0);
+ else
+ ClientNMB = 0;
+
+ ClientDGRAM = open_socket_in(SOCK_DGRAM,DGRAM_PORT,3);
+
+ if (ClientNMB == -1)
+ return(False);
+
+ signal(SIGPIPE, SIGNAL_CAST sig_pipe);
+
+ set_socket_options(ClientNMB,"SO_BROADCAST");
+ set_socket_options(ClientDGRAM,"SO_BROADCAST");
+ set_socket_options(ClientNMB,user_socket_options);
+
+ DEBUG(3, ("Socket opened.\n"));
+ return True;
+};
+
+
+/****************************************************************************
+ initialise connect, service and file structs
+****************************************************************************/
+static BOOL init_structs(void )
+{
+ if (!get_myname(myhostname,got_myip?NULL:&myip))
+ return(False);
+
+ /* Read the broadcast address from the interface */
+ {
+ struct in_addr ip0,ip1,ip2;
+
+ ip0 = myip;
+
+ if (!(got_bcast && got_nmask))
+ {
+ get_broadcast(&ip0,&ip1,&ip2);
+
+ if (!got_myip)
+ myip = ip0;
+
+ if (!got_bcast)
+ bcast_ip = ip1;
+
+ if (!got_nmask)
+ Netmask = ip2;
+ }
+
+ DEBUG(1,("Using IP %s ",inet_ntoa(myip))); /* core dump reported
+ doing this. Why?? XXXXX */
+ DEBUG(1,("broadcast %s ",inet_ntoa(bcast_ip)));
+ DEBUG(1,("netmask %s\n",inet_ntoa(Netmask)));
+
+ }
+
+ if (! *myname) {
+ char *p;
+ strcpy(myname,myhostname);
+ p = strchr(myname,'.');
+ if (p) *p = 0;
+ }
+
+ add_host_name(myname,0x20,&myip);
+ add_host_name(myname,0x0,&myip);
+ add_host_name(myname,0x3,&myip);
+
+ return True;
+}
+
+/****************************************************************************
+usage on the program
+****************************************************************************/
+static void usage(char *pname)
+{
+ DEBUG(0,("Incorrect program usage - is the command line correct?\n"));
+
+ printf("Usage: %s [-n name] [-B bcast address] [-D] [-p port] [-d debuglevel] [-l log basename]\n",pname);
+ printf("Version %s\n",VERSION);
+ printf("\t-D become a daemon\n");
+ printf("\t-P passive only. don't respond\n");
+ printf("\t-R only reply to queries, don't actively send claims\n");
+ printf("\t-p port listen on the specified port\n");
+ printf("\t-d debuglevel set the debuglevel\n");
+ printf("\t-l log basename. Basename for log/debug files\n");
+ printf("\t-n netbiosname. the netbios name to advertise for this host\n");
+ printf("\t-B broadcast address the address to use for broadcasts\n");
+ printf("\t-N netmask the netmask to use for subnet determination\n");
+ printf("\t-L name lookup this netbios name then exit\n");
+ printf("\t-S serve queries via DNS if not on the same subnet\n");
+ printf("\t-H hosts file load a netbios hosts file\n");
+ printf("\t-G group name add a group name to be part of\n");
+ printf("\t-b toggles browsing support (defaults to on)\n");
+ printf("\t-M group name searches for a master browser for the given group\n");
+ printf("\t-T interval sets the browse announcement interval in seconds\n");
+ printf("\t-C comment sets the machine comment that appears in browse lists\n");
+ printf("\n");
+}
+
+
+/****************************************************************************
+ main program
+****************************************************************************/
+int main(int argc,char *argv[])
+{
+ int port = NMB_PORT;
+ int opt;
+ unsigned int lookup_type = 0;
+ extern FILE *dbf;
+ extern char *optarg;
+
+ *lookup = *host_file = 0;
+
+ TimeInit();
+
+ charset_initialise();
+
+ strcpy(debugf,NMBLOGFILE);
+
+#ifdef LMHOSTSFILE
+ strcpy(host_file,LMHOSTSFILE);
+#endif
+
+ /* this is for people who can't start the program correctly */
+ while (argc > 1 && (*argv[1] != '-'))
+ {
+ argv++;
+ argc--;
+ }
+
+ fault_setup(fault_continue);
+
+ signal(SIGHUP,SIGNAL_CAST sig_hup);
+
+
+ while ((opt = getopt (argc, argv, "T:O:M:I:C:bAL:i:B:N:Rn:l:d:Dp:hPSH:G:")) != EOF)
+ switch (opt)
+ {
+ case 'T':
+ browse_interval = atoi(optarg);
+ browse_interval = MAX(browse_interval,10);
+ break;
+ case 'O':
+ strcpy(user_socket_options,optarg);
+ break;
+ case 'C':
+ strcpy(comment,optarg);
+ break;
+ case 'G':
+ add_group_name(optarg);
+ break;
+ case 'A':
+ dns_serve = True;
+ break;
+ case 'H':
+ strcpy(host_file,optarg);
+ break;
+ case 'I':
+ {
+ unsigned long a = interpret_addr(optarg);
+ putip((char *)&myip,(char *)&a);
+ got_myip = True;
+ }
+ break;
+ case 'B':
+ {
+ unsigned long a = interpret_addr(optarg);
+ putip((char *)&bcast_ip,(char *)&a);
+ got_bcast = True;
+ }
+ break;
+ case 'N':
+ {
+ unsigned long a = interpret_addr(optarg);
+ putip((char *)&Netmask,(char *)&a);
+ got_nmask = True;
+ }
+ break;
+ case 'n':
+ strcpy(myname,optarg);
+ break;
+ case 'P':
+ {
+ extern BOOL passive;
+ passive = True;
+ }
+ break;
+ case 'S':
+ dns_serve = !dns_serve;
+ break;
+ case 'l':
+ sprintf(debugf,"%s.nmb",optarg);
+ break;
+ case 'i':
+ strcpy(scope,optarg);
+ strupper(scope);
+ break;
+ case 'L':
+ strcpy(lookup,optarg);
+ break;
+ case 'M':
+ if (*optarg == '-') {
+ strcpy(lookup,"\01\02__MSBROWSE__\02");
+ lookup_type = 1;
+ } else {
+ strcpy(lookup,optarg);
+ lookup_type = 0x1d;
+ }
+ break;
+ case 'D':
+ is_daemon = True;
+ break;
+ case 'd':
+ DEBUGLEVEL = atoi(optarg);
+ break;
+ case 'p':
+ port = atoi(optarg);
+ break;
+ case 'h':
+ usage(argv[0]);
+ exit(0);
+ break;
+ default:
+ usage(argv[0]);
+ exit(1);
+ }
+
+
+ if (*lookup)
+ DEBUGLEVEL++;
+
+ if (DEBUGLEVEL > 10)
+ {
+ extern FILE *login,*logout;
+ pstring fname;
+ sprintf(fname,"%s.in",debugf);
+ login = fopen(fname,"w");
+ sprintf(fname,"%s.out",debugf);
+ logout = fopen(fname,"w");
+ }
+
+ if (*lookup)
+ {
+ if (dbf)
+ fclose(dbf);
+ dbf = stdout;
+ }
+
+ DEBUG(1,("%s netbios nameserver version %s started\n",timestring(),VERSION));
+ DEBUG(1,("Copyright Andrew Tridgell 1994\n"));
+
+ if (*host_file)
+ {
+ load_hosts_file(host_file);
+ DEBUG(3,("Loaded hosts file\n"));
+ }
+
+ init_structs();
+
+ if (*lookup) {
+ BOOL bcast = True;
+ int retries = 2;
+ char *p = strchr(lookup,'#');
+ struct in_addr ip;
+ if (p) {
+ *p = 0;
+ sscanf(p+1,"%x",&lookup_type);
+ bcast = False;
+ retries = 1;
+ }
+ if (!open_sockets(True,port)) return(1);
+ while (retries--)
+ if (name_query(lookup,lookup_type,bcast,True,bcast_ip,&ip)) {
+ printf("%s %s\n",inet_ntoa(ip),lookup);
+ name_status(lookup,lookup_type,ip,NULL);
+ return(0);
+ }
+ printf("couldn't find name %s\n",lookup);
+ return(0);
+ }
+
+ if (!*comment)
+ strcpy(comment,"Samba %v");
+ string_sub(comment,"%v",VERSION);
+ string_sub(comment,"%h",myhostname);
+
+ check_names();
+
+ DEBUG(3,("Checked names\n"));
+
+ dump_names();
+
+ DEBUG(3,("Dumped names\n"));
+
+ if (!is_daemon && !is_a_socket(0)) {
+ DEBUG(0,("standard input is not a socket, assuming -D option\n"));
+ is_daemon = True;
+ }
+
+
+ if (is_daemon) {
+ DEBUG(2,("%s becoming a daemon\n",timestring()));
+ become_daemon();
+ }
+
+
+ DEBUG(3,("Opening sockets\n"));
+
+ if (open_sockets(is_daemon,port))
+ {
+ process();
+ close_sockets();
+ }
+
+ if (dbf)
+ fclose(dbf);
+ return(0);
+}
diff -u -r --new-file last-version/source/nmblib.c samba-1.9.14p3/source/nmblib.c
--- last-version/source/nmblib.c Thu Jan 1 10:00:00 1970
+++ samba-1.9.14p3/source/nmblib.c Tue Nov 7 22:25:10 1995
@@ -0,0 +1,504 @@
+/*
+ Unix SMB/Netbios implementation.
+ Version 1.9.
+ NBT netbios routines and daemon - version 2
+ Copyright (C) Andrew Tridgell 1994-1995
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include "includes.h"
+#include "nameserv.h"
+
+extern int DEBUGLEVEL;
+
+int num_good_sends=0;
+int num_good_receives=0;
+
+/*******************************************************************
+ handle "compressed" name pointers
+ ******************************************************************/
+static BOOL handle_name_ptrs(unsigned char *ubuf,int *offset,int length,
+ BOOL *got_pointer,int *ret)
+{
+ int loop_count=0;
+
+ while ((ubuf[*offset] & 0xC0) == 0xC0) {
+ if (!*got_pointer) (*ret) += 2;
+ (*got_pointer)=True;
+ (*offset) = ((ubuf[*offset] & ~0xC0)<<8) | ubuf[(*offset)+1];
+ if (loop_count++ == 10 || (*offset) < 0 || (*offset)>(length-2)) {
+ return(False);
+ }
+ }
+ return(True);
+}
+
+/*******************************************************************
+ parse a nmb name from "compressed" format to something readable
+ return the space taken by the name, or 0 if the name is invalid
+ ******************************************************************/
+static int parse_nmb_name(char *inbuf,int offset,int length,
+ struct nmb_name *name)
+{
+ int m,n=0;
+ unsigned char *ubuf = (unsigned char *)inbuf;
+ int ret = 0;
+ BOOL got_pointer=False;
+
+ if (length - offset < 2) return(0);
+
+ /* handle initial name pointers */
+ if (!handle_name_ptrs(ubuf,&offset,length,&got_pointer,&ret)) return(0);
+
+ m = ubuf[offset];
+
+ if (!m) return(0);
+ if ((m & 0xC0) || offset+m+2 > length) return(0);
+
+ bzero((char *)name,sizeof(*name));
+
+ /* the "compressed" part */
+ if (!got_pointer) ret += m + 2;
+ offset++;
+ while (m) {
+ unsigned char c1,c2;
+ c1 = ubuf[offset++]-'A';
+ c2 = ubuf[offset++]-'A';
+ if ((c1 & 0xF0) || (c2 & 0xF0)) return(0);
+ name->name[n++] = (c1<<4) | c2;
+ m -= 2;
+ }
+ name->name[n] = 0;
+
+ if (n==16) {
+ /* parse out the name type,
+ its always in the 16th byte of the name */
+ name->name_type = name->name[15];
+
+ /* remove trailing spaces */
+ name->name[15] = 0;
+ n = 14;
+ while (n && name->name[n]==' ') name->name[n--] = 0;
+ }
+
+ /* now the domain parts (if any) */
+ n = 0;
+ while ((m=ubuf[offset])) {
+ /* we can have pointers within the domain part as well */
+ if (!handle_name_ptrs(ubuf,&offset,length,&got_pointer,&ret)) return(0);
+
+ if (!got_pointer) ret += m+1;
+ if (n) name->scope[n++] = '.';
+ if (m+2+offset>length || n+m+1>sizeof(name->scope)) return(0);
+ offset++;
+ while (m--) name->scope[n++] = (char)ubuf[offset++];
+ }
+ name->scope[n++] = 0;
+
+ return(ret);
+}
+
+
+/*******************************************************************
+ put a compressed nmb name into a buffer. return the length of the
+ compressed name
+ ******************************************************************/
+static int put_nmb_name(char *buf,int offset,struct nmb_name *name)
+{
+ int ret,m;
+ char buf1[16];
+ char *p;
+
+ sprintf(buf1,"%-15.15s%c",name->name,name->name_type);
+ buf[offset] = 0x20;
+
+ ret = 34;
+
+ for (m=0;m<16;m++) {
+ buf[offset+1+2*m] = 'A' + ((buf1[m]>>4)&0xF);
+ buf[offset+2+2*m] = 'A' + (buf1[m]&0xF);
+ }
+ offset += 33;
+
+ buf[offset] = 0;
+
+ if (name->scope[0]) {
+ /* XXXX this scope handling needs testing */
+ ret += strlen(name->scope) + 1;
+ strcpy(&buf[offset+1],name->scope);
+
+ p = &buf[offset+1];
+ while ((p = strchr(p,'.'))) {
+ buf[offset] = PTR_DIFF(p,&buf[offset]);
+ offset += buf[offset];
+ p = &buf[offset+1];
+ }
+ buf[offset] = strlen(&buf[offset+1]);
+ }
+
+ return(ret);
+}
+
+
+/*******************************************************************
+ allocate are parse some resource records
+ ******************************************************************/
+static BOOL parse_alloc_res_rec(char *inbuf,int *offset,int length,
+ struct res_rec **recs,
+ int count)
+{
+ int i;
+ *recs = (struct res_rec *)malloc(sizeof(**recs)*count);
+ if (!*recs) return(False);
+
+ bzero(*recs,sizeof(**recs)*count);
+
+ for (i=0;i<count;i++) {
+ int l = parse_nmb_name(inbuf,*offset,length,&(*recs)[i].rr_name);
+ (*offset) += l;
+ if (!l || (*offset)+10 > length) {
+ free(*recs);
+ return(False);
+ }
+ (*recs)[i].rr_type = RSVAL(inbuf,(*offset));
+ (*recs)[i].rr_class = RSVAL(inbuf,(*offset)+2);
+ (*recs)[i].ttl = RIVAL(inbuf,(*offset)+4);
+ (*recs)[i].rdlength = RSVAL(inbuf,(*offset)+8);
+ (*offset) += 10;
+ if ((*recs)[i].rdlength>sizeof((*recs)[i].rdata) ||
+ (*offset)+(*recs)[i].rdlength > length) {
+ free(*recs);
+ return(False);
+ }
+ memcpy((*recs)[i].rdata,inbuf+(*offset),(*recs)[i].rdlength);
+ (*offset) += (*recs)[i].rdlength;
+ }
+ return(True);
+}
+
+/*******************************************************************
+ put a resource record into a packet
+ ******************************************************************/
+static int put_res_rec(char *buf,int offset,struct res_rec *recs,int count)
+{
+ int ret=0;
+ int i;
+
+ for (i=0;i<count;i++) {
+ int l = put_nmb_name(buf,offset,&recs[i].rr_name);
+ offset += l;
+ ret += l;
+ RSSVAL(buf,offset,recs[i].rr_type);
+ RSSVAL(buf,offset+2,recs[i].rr_class);
+ RSIVAL(buf,offset+4,recs[i].ttl);
+ RSSVAL(buf,offset+8,recs[i].rdlength);
+ memcpy(buf+offset+10,recs[i].rdata,recs[i].rdlength);
+ offset += 10+recs[i].rdlength;
+ ret += 10+recs[i].rdlength;
+ }
+
+ return(ret);
+}
+
+/*******************************************************************
+ parse a dgram packet. Return False if the packet can't be parsed
+ or is invalid for some reason, True otherwise
+ ******************************************************************/
+static BOOL parse_dgram(char *inbuf,int length,struct dgram_packet *dgram)
+{
+ int offset;
+
+ bzero((char *)dgram,sizeof(*dgram));
+
+ if (length < 14) return(False);
+
+ dgram->header.res = RSVAL(inbuf,0);
+ dgram->header.id = RSVAL(inbuf,2);
+ putip((char *)&dgram->header.ip,inbuf+4);
+ dgram->header.port = RSVAL(inbuf,8);
+ dgram->header.length = RSVAL(inbuf,10);
+ dgram->header.res2 = RSVAL(inbuf,12);
+
+ offset = 14;
+ offset += parse_nmb_name(inbuf,offset,length,&dgram->header.source_name);
+ offset += parse_nmb_name(inbuf,offset,length,&dgram->header.dest_name);
+
+ if (offset >= length || (length-offset > sizeof(dgram->smb_data)))
+ return(False);
+
+ dgram->smbsize = length-offset;
+ memcpy(dgram->smb_data,inbuf+offset,dgram->smbsize);
+
+ return(True);
+}
+
+
+/*******************************************************************
+ parse a nmb packet. Return False if the packet can't be parsed
+ or is invalid for some reason, True otherwise
+ ******************************************************************/
+static BOOL parse_nmb(char *inbuf,int length,struct nmb_packet *nmb)
+{
+ int nm_flags,offset;
+
+ bzero((char *)nmb,sizeof(*nmb));
+
+ if (length < 12) return(False);
+
+ /* parse the header */
+ nmb->header.name_trn_id = RSVAL(inbuf,0);
+ nmb->header.opcode = (CVAL(inbuf,2) >> 3) & 0xF;
+ nmb->header.response = ((CVAL(inbuf,2)>>7)&1)?True:False;
+ nm_flags = ((CVAL(inbuf,2) & 0x7) << 4) + (CVAL(inbuf,3)>>4);
+ nmb->header.nm_flags.bcast = (nm_flags&1)?True:False;
+ nmb->header.nm_flags.recursion_available = (nm_flags&8)?True:False;
+ nmb->header.nm_flags.recursion_desired = (nm_flags&0x10)?True:False;
+ nmb->header.nm_flags.trunc = (nm_flags&0x20)?True:False;
+ nmb->header.nm_flags.authoritative = (nm_flags&0x40)?True:False;
+ nmb->header.rcode = CVAL(inbuf,3) & 0xF;
+ nmb->header.qdcount = RSVAL(inbuf,4);
+ nmb->header.ancount = RSVAL(inbuf,6);
+ nmb->header.nscount = RSVAL(inbuf,8);
+ nmb->header.arcount = RSVAL(inbuf,10);
+
+ if (nmb->header.qdcount) {
+ offset = parse_nmb_name(inbuf,12,length,&nmb->question.question_name);
+ if (!offset) return(False);
+
+ if (length - (12+offset) < 4) return(False);
+ nmb->question.question_type = RSVAL(inbuf,12+offset);
+ nmb->question.question_class = RSVAL(inbuf,12+offset+2);
+
+ offset += 12+4;
+ } else {
+ offset = 12;
+ }
+
+ /* and any resource records */
+ if (nmb->header.ancount &&
+ !parse_alloc_res_rec(inbuf,&offset,length,&nmb->answers,
+ nmb->header.ancount))
+ return(False);
+
+ if (nmb->header.nscount &&
+ !parse_alloc_res_rec(inbuf,&offset,length,&nmb->nsrecs,
+ nmb->header.nscount))
+ return(False);
+
+ if (nmb->header.arcount &&
+ !parse_alloc_res_rec(inbuf,&offset,length,&nmb->additional,
+ nmb->header.arcount))
+ return(False);
+
+ return(True);
+}
+
+/*******************************************************************
+ free up any resources associated with an nmb packet
+ ******************************************************************/
+void free_nmb_packet(struct nmb_packet *nmb)
+{
+ if (nmb->answers) free(nmb->answers);
+ if (nmb->nsrecs) free(nmb->nsrecs);
+ if (nmb->additional) free(nmb->additional);
+}
+
+/*******************************************************************
+ free up any resources associated with a packet
+ ******************************************************************/
+void free_packet(struct packet_struct *packet)
+{
+ free_nmb_packet(&packet->packet.nmb);
+ free(packet);
+}
+
+/*******************************************************************
+ read a packet from a socket and parse it, returning a packet ready
+ to be used or put on the queue. This assumes a UDP socket
+ ******************************************************************/
+struct packet_struct *read_packet(int fd,enum packet_type packet_type)
+{
+ extern struct in_addr lastip;
+ extern int lastport;
+ struct packet_struct *packet;
+ char buf[MAX_DGRAM_SIZE];
+ int length;
+ BOOL ok=False;
+
+ length = read_udp_socket(fd,buf,sizeof(buf));
+ if (length < MIN_DGRAM_SIZE) return(NULL);
+
+ packet = (struct packet_struct *)malloc(sizeof(*packet));
+ if (!packet) return(NULL);
+
+ packet->next = NULL;
+ packet->prev = NULL;
+ packet->ip = lastip;
+ packet->port = lastport;
+ packet->fd = fd;
+ packet->timestamp = time(NULL);
+ packet->packet_type = packet_type;
+ switch (packet_type)
+ {
+ case NMB_PACKET:
+ ok = parse_nmb(buf,length,&packet->packet.nmb);
+ break;
+
+ case DGRAM_PACKET:
+ ok = parse_dgram(buf,length,&packet->packet.dgram);
+ break;
+ }
+ if (!ok) {
+ free(packet);
+ return(NULL);
+ }
+
+ num_good_receives++;
+
+ return(packet);
+}
+
+
+/*******************************************************************
+ send a udp packet on a already open socket
+ ******************************************************************/
+static BOOL send_udp(int fd,char *buf,int len,struct in_addr *ip,int port)
+{
+ BOOL ret;
+ struct sockaddr_in sock_out;
+
+ /* set the address and port */
+ bzero((char *)&sock_out,sizeof(sock_out));
+ putip((char *)&sock_out.sin_addr,(char *)ip);
+ sock_out.sin_port = htons( port );
+ sock_out.sin_family = AF_INET;
+
+ DEBUG(3,("sending a packet of len %d to (%s) on port 137 of type DGRAM\n",
+ len,inet_ntoa(*ip)));
+
+ ret = (sendto(fd,buf,len,0,(struct sockaddr *)&sock_out,
+ sizeof(sock_out)) >= 0);
+
+ if (!ret)
+ DEBUG(0,("Send packet failed. ERRNO=%d\n",errno));
+
+ if (ret)
+ num_good_sends++;
+
+ return(ret);
+}
+
+
+/*******************************************************************
+ build a nmb packet ready for sending
+
+ XXXX this currently relies on not being passed something that expands
+ to a packet too big for the buffer. Eventually this should be
+ changed to set the trunc bit so the receiver can request the rest
+ via tcp (when that becomes supported)
+ ******************************************************************/
+static int build_nmb(char *buf,struct packet_struct *p)
+{
+ struct nmb_packet *nmb = &p->packet.nmb;
+ unsigned char *ubuf = (unsigned char *)buf;
+ int offset=0;
+
+ /* put in the header */
+ RSSVAL(ubuf,offset,nmb->header.name_trn_id);
+ ubuf[offset+2] = (nmb->header.opcode & 0xF) << 3;
+ if (nmb->header.response) ubuf[offset+2] |= (1<<7);
+ if (nmb->header.nm_flags.authoritative) ubuf[offset+2] |= 0x4;
+ if (nmb->header.nm_flags.trunc) ubuf[offset+2] |= 0x2;
+ if (nmb->header.nm_flags.recursion_desired) ubuf[offset+2] |= 0x1;
+ if (nmb->header.nm_flags.recursion_available) ubuf[offset+3] |= 0x80;
+ if (nmb->header.nm_flags.bcast) ubuf[offset+3] |= 0x10;
+ ubuf[offset+3] |= (nmb->header.rcode & 0xF);
+ RSSVAL(ubuf,offset+4,nmb->header.qdcount);
+ RSSVAL(ubuf,offset+6,nmb->header.ancount);
+ RSSVAL(ubuf,offset+8,nmb->header.nscount);
+ RSSVAL(ubuf,offset+10,nmb->header.arcount);
+
+ offset += 12;
+ if (nmb->header.qdcount) {
+ /* XXXX this doesn't handle a qdcount of > 1 */
+ offset += put_nmb_name(ubuf,offset,&nmb->question.question_name);
+ RSSVAL(ubuf,offset,nmb->question.question_type);
+ RSSVAL(ubuf,offset+2,nmb->question.question_class);
+ offset += 4;
+ }
+
+ if (nmb->header.ancount)
+ offset += put_res_rec(ubuf,offset,nmb->answers,nmb->header.ancount);
+
+ if (nmb->header.nscount)
+ offset += put_res_rec(ubuf,offset,nmb->nsrecs,nmb->header.nscount);
+
+ if (nmb->header.arcount)
+ offset += put_res_rec(ubuf,offset,nmb->additional,nmb->header.arcount);
+
+ return(offset);
+}
+
+
+/*******************************************************************
+ send a packet_struct
+ ******************************************************************/
+BOOL send_packet(struct packet_struct *p)
+{
+ char buf[1024];
+ int len=0;
+
+ bzero(buf,sizeof(buf));
+
+ switch (p->packet_type)
+ {
+ case NMB_PACKET:
+ len = build_nmb(buf,p);
+ break;
+
+ case DGRAM_PACKET:
+ /* len = build_dgram(buf,p); */
+ break;
+ }
+
+ if (!len) return(False);
+
+ return(send_udp(p->fd,buf,len,&p->ip,p->port));
+}
+
+/****************************************************************************
+ receive a packet with timeout on a open UDP filedescriptor
+ The timeout is in milliseconds
+ ***************************************************************************/
+struct packet_struct *receive_packet(int fd,enum packet_type type,int t)
+{
+ fd_set fds;
+ struct timeval timeout;
+
+ FD_ZERO(&fds);
+ FD_SET(fd,&fds);
+ timeout.tv_sec = t/1000;
+ timeout.tv_usec = 1000*(t%1000);
+
+ sys_select(&fds,&timeout);
+
+ if (FD_ISSET(fd,&fds))
+ return(read_packet(fd,type));
+
+ return(NULL);
+}
+
diff -u -r --new-file last-version/source/password.c samba-1.9.14p3/source/password.c
--- last-version/source/password.c Fri Sep 22 10:37:06 1995
+++ samba-1.9.14p3/source/password.c Sun Nov 5 15:51:20 1995
@@ -568,7 +568,7 @@
/****************************************************************************
check if a username/password is OK
****************************************************************************/
-BOOL password_ok(char *user,char *password, int pwlen, struct passwd *pwd)
+BOOL password_ok(char *user,char *password, int pwlen, struct passwd *pwd, BOOL is_nt_password)
{
pstring pass2;
int level = lp_passwordlevel();
@@ -641,6 +641,26 @@
return(False);
}
+ if(Protocol >= PROTOCOL_NT1 && is_nt_password)
+ {
+ /* We have the NT MD4 hash challenge available - see if we can
+ use it (ie. does it exist in the smbpasswd file).
+ */
+ if(smb_pass->smb_nt_passwd != NULL)
+ {
+ DEBUG(4,("Checking NT MD4 password\n"));
+ if(smb_password_check(password, smb_pass->smb_nt_passwd, challenge))
+ {
+ update_protected_database(user,True);
+ return(True);
+ }
+ DEBUG(4,("NT MD4 password check failed\n"));
+ return (False);
+ }
+ }
+
+ /* Try against the lanman password */
+
if(smb_password_check(password, smb_pass->smb_passwd, challenge))
{
update_protected_database(user,True);
@@ -819,7 +839,7 @@
while (getnetgrent(&host, &user, &domain)) {
if (user) {
if (user_ok(user, snum) &&
- password_ok(user,password,pwlen,NULL)) {
+ password_ok(user,password,pwlen,NULL,False)) {
endnetgrent();
return(user);
}
@@ -841,7 +861,7 @@
static fstring name;
strcpy(name,*member);
if (user_ok(name,snum) &&
- password_ok(name,password,pwlen,NULL))
+ password_ok(name,password,pwlen,NULL,False))
return(&name[0]);
member++;
}
@@ -854,7 +874,7 @@
while (pwd = getpwent ()) {
if (*(pwd->pw_passwd) && pwd->pw_gid == gptr->gr_gid) {
/* This Entry have PASSWORD and same GID then check pwd */
- if (password_ok(NULL, password, pwlen, pwd)) {
+ if (password_ok(NULL, password, pwlen, pwd,False)) {
strcpy(tm, pwd->pw_name);
endpwent ();
return tm;
@@ -905,14 +925,14 @@
/* check the given username and password */
if (!ok && (*user) && user_ok(user,snum)) {
- ok = password_ok(user,password, pwlen, NULL);
+ ok = password_ok(user,password, pwlen, NULL, False);
if (ok) DEBUG(3,("ACCEPTED: given username password ok\n"));
}
/* check for a previously registered guest username */
if (!ok && (vuid >= 0) && validated_users[vuid].guest) {
if (user_ok(validated_users[vuid].name,snum) &&
- password_ok(validated_users[vuid].name, password, pwlen, NULL)) {
+ password_ok(validated_users[vuid].name, password, pwlen, NULL, False)) {
strcpy(user, validated_users[vuid].name);
validated_users[vuid].guest = False;
DEBUG(3,("ACCEPTED: given password with registered user %s\n", user));
@@ -936,7 +956,7 @@
strcpy(user2,auser);
if (!user_ok(user2,snum)) continue;
- if (password_ok(user2,password, pwlen, NULL)) {
+ if (password_ok(user2,password, pwlen, NULL, False)) {
ok = True;
strcpy(user,user2);
DEBUG(3,("ACCEPTED: session list username and given password ok\n"));
@@ -988,7 +1008,7 @@
fstring user2;
strcpy(user2,auser);
if (user_ok(user2,snum) &&
- password_ok(user2,password,pwlen,NULL))
+ password_ok(user2,password,pwlen,NULL, False))
{
ok = True;
strcpy(user,user2);
diff -u -r --new-file last-version/source/printing.c samba-1.9.14p3/source/printing.c
--- last-version/source/printing.c Thu Nov 2 09:59:36 1995
+++ samba-1.9.14p3/source/printing.c Mon Nov 6 16:53:58 1995
@@ -83,7 +83,7 @@
the subshell causes a "cd" to be executed.
Only use the full path if there isn't a / preceding the %s */
if (iOffset==0 || syscmd[iOffset-1] != '/') {
- StrnCpy(filename,Connections[cnum].connectpath,sizeof(filename));
+ StrnCpy(filename,Connections[cnum].connectpath,sizeof(filename)-1);
trim_string(filename,"","/");
strcat(filename,"/");
strcat(filename,filename1);
@@ -143,7 +143,10 @@
lpq_reset(snum);
}
+static char *Months[13] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", "Err"};
+
/*******************************************************************
process time fields
********************************************************************/
@@ -156,8 +159,6 @@
struct tm *t;
int i, day, hour, min, sec;
char *c;
- const char *Months[13] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
- "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", "Err" };
for (i=0; i<13; i++) if (!strncmp(tok[ptr], Months[i],3)) break; /* Find month */
if (i<12) {
@@ -186,7 +187,6 @@
jobtime = mktime(t);
}
}
- jobtime += GMT_TO_LOCAL*TimeDiff(jobtime);
return jobtime;
}
diff -u -r --new-file last-version/source/reply.c samba-1.9.14p3/source/reply.c
--- last-version/source/reply.c Sat Nov 4 22:32:47 1995
+++ samba-1.9.14p3/source/reply.c Mon Nov 6 16:14:59 1995
@@ -290,6 +290,9 @@
uint32 smb_sesskey;
int smb_apasslen;
pstring smb_apasswd;
+ int smb_ntpasslen = 0;
+ pstring smb_ntpasswd;
+ BOOL valid_nt_password = False;
pstring user;
BOOL guest=False;
@@ -316,10 +319,11 @@
if (passlen2 > 256) passlen2 = 0; /* I don't know why NT gives weird
lengths sometimes */
if(doencrypt) {
- /* Use the lanman2 password for now until the NT md4 password
- is worked out. */
+ /* Save the lanman2 password and the NT md4 password. */
smb_apasslen = passlen1;
memcpy(smb_apasswd,p,smb_apasslen);
+ smb_ntpasslen = passlen2;
+ memcpy(smb_ntpasswd,p+passlen1,smb_ntpasslen);
} else {
/* for Win95 */
if (passlen1 > passlen2) {
@@ -359,8 +363,17 @@
guest = True;
/* now check if it's a valid username/password */
- if (!guest && !password_ok(user,smb_apasswd,smb_apasslen,NULL))
+ /* If an NT password was supplied try and validate with that
+ first. This is superior as the passwords are mixed case 128 length unicode */
+ if(smb_ntpasslen && !guest)
{
+ if(!password_ok(user,smb_ntpasswd,smb_ntpasslen,NULL,True))
+ DEBUG(0,("NT Password did not match ! Defaulting to Lanman\n"));
+ else
+ valid_nt_password = True;
+ }
+ if (!valid_nt_password && !guest && !password_ok(user,smb_apasswd,smb_apasslen,NULL,False))
+ {
#if !GUEST_SESSSETUP
if (lp_security() >= SEC_USER)
return(ERROR(ERRSRV,ERRbadpw));
@@ -456,7 +469,7 @@
mode = SVAL(inbuf,smb_vwv0);
if (check_name(name,cnum))
- ok = directory_exist(name);
+ ok = directory_exist(name,NULL);
if (!ok)
return(ERROR(ERRDOS,ERRbadpath));
@@ -520,7 +533,7 @@
outsize = set_message(outbuf,10,0,True);
SSVAL(outbuf,smb_vwv0,mode);
- SIVAL(outbuf,smb_vwv1,mtime + GMT_TO_LOCAL * TimeDiff(mtime));
+ put_dos_date3(outbuf,smb_vwv1,mtime);
SIVAL(outbuf,smb_vwv3,size);
if (Protocol >= PROTOCOL_NT1) {
@@ -555,14 +568,14 @@
unix_convert(fname,cnum);
mode = SVAL(inbuf,smb_vwv0);
- mtime = IVAL(inbuf,smb_vwv1);
+ mtime = make_unix_date3(inbuf+smb_vwv1);
- if (directory_exist(fname))
+ if (directory_exist(fname,NULL))
mode |= aDIR;
if (check_name(fname,cnum))
ok = (dos_chmod(cnum,fname,mode) == 0);
- if (ok && mtime != 0)
- ok = set_filetime(fname,mtime + LOCAL_TO_GMT * TimeDiff(mtime));
+ if (ok)
+ ok = set_filetime(fname,mtime);
if (!ok)
return(UNIXERROR(ERRDOS,ERRnoaccess));
@@ -930,7 +943,7 @@
outsize = set_message(outbuf,7,0,True);
SSVAL(outbuf,smb_vwv0,fnum);
SSVAL(outbuf,smb_vwv1,fmode);
- SIVAL(outbuf,smb_vwv2,mtime + GMT_TO_LOCAL * TimeDiff(mtime));
+ put_dos_date3(outbuf,smb_vwv2,mtime);
SIVAL(outbuf,smb_vwv4,size);
SSVAL(outbuf,smb_vwv6,rmode);
@@ -955,7 +968,7 @@
#if 0
int open_flags = SVAL(inbuf,smb_vwv2);
int smb_sattr = SVAL(inbuf,smb_vwv4);
- uint32 smb_time = IVAL(inbuf,smb_vwv6);
+ uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
#endif
int smb_ofun = SVAL(inbuf,smb_vwv8);
int unixmode;
@@ -1007,7 +1020,7 @@
SSVAL(outbuf,smb_vwv1,(chain_size+outsize)-4);
SSVAL(outbuf,smb_vwv2,fnum);
SSVAL(outbuf,smb_vwv3,fmode);
- SIVAL(outbuf,smb_vwv4,mtime + GMT_TO_LOCAL * TimeDiff(mtime));
+ put_dos_date3(outbuf,smb_vwv4,mtime);
SIVAL(outbuf,smb_vwv6,size);
SSVAL(outbuf,smb_vwv8,rmode);
SSVAL(outbuf,smb_vwv11,smb_action);
@@ -1918,15 +1931,12 @@
err = Files[fnum].wbmpx_ptr->wr_error;
}
- mtime = IVAL(inbuf,smb_vwv1);
+ mtime = make_unix_date3(inbuf+smb_vwv1);
close_file(fnum);
/* try and set the date */
- if (mtime == 0 || mtime == -1)
- DEBUG(5,("not setting null date\n"));
- else
- set_filetime(Files[fnum].name,mtime + LOCAL_TO_GMT * TimeDiff(mtime));
+ set_filetime(Files[fnum].name,mtime);
/* We have a cached error */
if(eclass || err)
@@ -1961,7 +1971,7 @@
numtowrite = SVAL(inbuf,smb_vwv1);
startpos = IVAL(inbuf,smb_vwv2);
- mtime = IVAL(inbuf,smb_vwv4);
+ mtime = make_unix_date3(inbuf+smb_vwv4);
data = smb_buf(inbuf) + 1;
if (is_locked(fnum,cnum,numtowrite,startpos))
@@ -1973,10 +1983,7 @@
close_file(fnum);
- if (mtime == 0 || mtime == -1)
- DEBUG(5,("not setting null date\n"));
- else
- set_filetime(Files[fnum].name,mtime + LOCAL_TO_GMT * TimeDiff(mtime));
+ set_filetime(Files[fnum].name,mtime);
DEBUG(3,("%s writeclose fnum=%d cnum=%d num=%d wrote=%d (numopen=%d)\n",
timestring(),fnum,cnum,numtowrite,nwritten,
@@ -2516,6 +2523,7 @@
strcat(directory,mask);
if (resolve_wildcards(directory,newname) &&
can_rename(directory,cnum) &&
+ !file_exist(newname,NULL) &&
!sys_rename(directory,newname)) count++;
if (!count) exists = file_exist(directory,NULL);
} else {
@@ -2545,6 +2553,7 @@
if (!can_rename(fname,cnum)) continue;
strcpy(destname,newname);
if (resolve_wildcards(fname,destname) &&
+ !file_exist(destname,NULL) &&
!sys_rename(fname,destname)) count++;
DEBUG(3,("reply_mv : doing rename on %s -> %s\n",fname,destname));
}
@@ -2588,7 +2597,7 @@
ok = True;
else
{
- ok = directory_exist(newdir);
+ ok = directory_exist(newdir,NULL);
if (ok)
string_set(&Connections[cnum].connectpath,newdir);
}
@@ -2943,12 +2952,8 @@
/* Convert the DOS times into unix times. Ignore create
time as UNIX can't set this.
*/
-
- /* XXXX - should this include the DST offset? */
- unix_times.actime = make_unix_date2(inbuf+smb_vwv3,False);
- unix_times.modtime = make_unix_date2(inbuf+smb_vwv5,False);
- unix_times.actime += LOCAL_TO_GMT*TimeDiff(unix_times.actime);
- unix_times.modtime += LOCAL_TO_GMT*TimeDiff(unix_times.modtime);
+ unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
+ unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
/* Set the date on this file */
if(sys_utime(Files[fnum].name, &unix_times))
diff -u -r --new-file last-version/source/server.c samba-1.9.14p3/source/server.c
--- last-version/source/server.c Sat Nov 4 22:11:05 1995
+++ samba-1.9.14p3/source/server.c Tue Nov 7 18:24:54 1995
@@ -347,7 +347,8 @@
(strequal(dname,".") || strequal(dname,"..")))
continue;
- if (!name_convert(name2,dname,False,snum)) continue;
+ strcpy(name2,dname);
+ if (!name_map_mangle(name2,False,snum)) continue;
if ((mangled && mangled_equal(name,name2))
|| fname_equal(name, name2))
@@ -1709,8 +1710,7 @@
****************************************************************************/
BOOL unbecome_user(void )
{
- if (ChDir(OriginalDir) != 0)
- DEBUG(0,("%s chdir(%s) failed\n",timestring(),OriginalDir));
+ ChDir(OriginalDir);
if (done_become_user == -1)
return(False);
@@ -1747,7 +1747,8 @@
#endif
if (ChDir(OriginalDir) != 0)
- DEBUG(0,("%s chdir(%s) failed\n",timestring(),OriginalDir));
+ DEBUG(0,("%s chdir(%s) failed in unbecome_user\n",
+ timestring(),OriginalDir));
DEBUG(5,("unbecome_user now uid=(%d,%d) gid=(%d,%d)\n",
getuid(),geteuid(),getgid(),getegid()));
@@ -3143,7 +3144,7 @@
standard_sub(cnum,fname);
trim_string(fname,"","/");
- if (!directory_exist(fname))
+ if (!directory_exist(fname,NULL))
mkdir(fname,0755);
strcat(fname,"/");
@@ -3208,10 +3209,8 @@
crec.uid = Connections[cnum].uid;
crec.gid = Connections[cnum].gid;
StrnCpy(crec.name,lp_servicename(snum),sizeof(crec.name)-1);
- {
- time_t t = time(NULL);
- crec.start = t + GMT_TO_LOCAL*TimeDiff(t);
- }
+ crec.start = time(NULL);
+
{
extern struct from_host Client_info;
StrnCpy(crec.machine,Client_info.name,sizeof(crec.machine)-1);
@@ -3744,7 +3743,7 @@
uint32 a = interpret_addr("localhost");
putip((void *)&ip,(void *)&a);
*OutBuffer = 0;
- send_packet(OutBuffer,1,&ip,137,SOCK_DGRAM);
+ send_one_packet(OutBuffer,1,&ip,137,SOCK_DGRAM);
}
#endif
@@ -3963,6 +3962,8 @@
#ifdef OSF1_ENH_SEC
set_auth_parameters(argc,argv);
#endif
+
+ TimeInit();
charset_initialise();
diff -u -r --new-file last-version/source/smb.h samba-1.9.14p3/source/smb.h
--- last-version/source/smb.h Sat Nov 4 22:13:27 1995
+++ samba-1.9.14p3/source/smb.h Tue Nov 7 18:24:53 1995
@@ -210,6 +210,7 @@
int mode;
int uid;
int gid;
+ /* these times are normally kept in GMT */
time_t mtime;
time_t atime;
time_t ctime;
@@ -695,7 +696,7 @@
void add_session_user(char *user);
int valid_uid(int uid);
user_struct *get_valid_user_struct(int uid);
-BOOL password_ok(char *user,char *password, int pwlen, struct passwd *pwd);
+BOOL password_ok(char *user,char *password, int pwlen, struct passwd *pwd, BOOL nt_password);
void register_uid(int uid,int gid,char *name,BOOL guest);
BOOL fromhost(int sock,struct from_host *f);
BOOL strhasupper(char *s);
@@ -707,7 +708,7 @@
BOOL check_file_sharing(int cnum,char *fname);
char *StrCpy(char *dest,char *src);
int unix_error_packet(char *inbuf,char *outbuf,int def_class,uint32 def_code,int line);
-time_t make_unix_date2(void *date_ptr,BOOL add_dst);
+time_t make_unix_date2(void *date_ptr);
int cached_error_packet(char *inbuf,char *outbuf,int fnum,int line);
mode_t unix_mode(int cnum,int dosmode);
BOOL check_name(char *name,int cnum);
@@ -724,7 +725,7 @@
BOOL yield_connection(int cnum,char *name,int max_connections);
int count_chars(char *s,char c);
int smbrun(char *,char *);
-BOOL name_convert(char *OutName,char *InName,BOOL need83,int snum);
+BOOL name_map_mangle(char *OutName,BOOL need83,int snum);
struct hostent *Get_Hostbyname(char *name);
struct passwd *Get_Pwnam(char *user,BOOL allow_change);
void Abort(void);
@@ -738,7 +739,9 @@
void string_free(char **s);
char *attrib_string(int mode);
void unix_format(char *fname);
-BOOL directory_exist(char *dname);
+BOOL directory_exist(char *dname,struct stat *st);
+time_t make_unix_date3(void *date_ptr);
+void put_dos_date3(char *buf,int offset,time_t unixdate);
void make_dir_struct(char *buf,char *mask,char *fname,unsigned int size,int mode,time_t date);
BOOL in_list(char *s,char *list,BOOL case_sensitive);
void strupper(char *s);
@@ -767,7 +770,7 @@
int dos_mode(int ,char *,struct stat *);
char *timestring();
BOOL ip_equal(struct in_addr *ip1,struct in_addr *ip2);
-BOOL send_packet(char *buf,int len,struct in_addr *ip,int port,int type);
+BOOL send_one_packet(char *buf,int len,struct in_addr *ip,int port,int type);
char *get_home_dir(char *);
int set_filelen(int fd, long len);
void put_dos_date(char *buf,int offset,time_t unixdate);
@@ -776,7 +779,7 @@
int name_len(char *s);
void dos_clean_name(char *s);
void unix_clean_name(char *s);
-time_t make_unix_date(void *date_ptr,BOOL add_dst);
+time_t make_unix_date(void *date_ptr);
BOOL lanman2_match( char *str, char *regexp, int case_sig, BOOL autoext);
BOOL trim_string(char *s,char *front,char *back);
int byte_checksum(char *buf,int len);
diff -u -r --new-file last-version/source/smbencrypt.c samba-1.9.14p3/source/smbencrypt.c
--- last-version/source/smbencrypt.c Tue Jul 11 21:56:15 1995
+++ samba-1.9.14p3/source/smbencrypt.c Sun Nov 5 15:46:54 1995
@@ -24,12 +24,24 @@
#include "includes.h"
#include "loadparm.h"
#include "des.h"
+#include "md4.h"
extern int DEBUGLEVEL;
#ifndef uchar
#define uchar unsigned char
#endif
+#ifndef int16
+#define int16 unsigned short
+#endif
+#ifndef uint16
+#define uint16 unsigned short
+#endif
+#ifndef uint32
+#define uint32 unsigned int
+#endif
+
+#include "byteorder.h"
void str_to_key(uchar *str,uchar *key)
{
@@ -110,6 +122,81 @@
E_P16(p14, p21);
E_P24(p21, c8, p24);
}
+
+/* Routines for Windows NT MD4 Hash functions. */
+static int _my_wcslen(int16 *str)
+{
+ int len = 0;
+ while(*str++ != 0)
+ len++;
+ return len;
+}
+
+/*
+ * Convert a string into an NT UNICODE string.
+ * Note that regardless of processor type
+ * this must be in intel (little-endian)
+ * format.
+ */
+
+static int _my_mbstowcs(int16 *dst, uchar *src, int len)
+{
+ int i;
+ int16 val;
+
+ for(i = 0; i < len; i++) {
+ val = *src;
+ SSVAL(dst,0,val);
+ dst++;
+ src++;
+ if(val == 0)
+ break;
+ }
+ return i;
+}
+
+/*
+ * Creates the MD4 Hash of the users password in NT UNICODE.
+ */
+
+void E_md4hash(uchar *passwd, uchar *p16)
+{
+ int i, len;
+ int16 wpwd[129];
+ MDstruct MD;
+
+ /* Password cannot be longer than 128 characters */
+ len = strlen(passwd);
+ if(len > 128)
+ len = 128;
+ /* Password must be converted to NT unicode */
+ _my_mbstowcs( wpwd, passwd, len);
+ wpwd[len] = 0; /* Ensure string is null terminated */
+ /* Calculate length in bytes */
+ len = _my_wcslen(wpwd) * sizeof(int16);
+
+ MDbegin(&MD);
+ for(i = 0; i + 64 <= len; i += 64)
+ MDupdate(&MD,wpwd + (i/2), 512);
+ MDupdate(&MD,wpwd + (i/2),(len-i)*8);
+ SIVAL(p16,0,MD.buffer[0]);
+ SIVAL(p16,4,MD.buffer[1]);
+ SIVAL(p16,8,MD.buffer[2]);
+ SIVAL(p16,12,MD.buffer[3]);
+}
+
+/* Does the NT MD4 hash then des encryption. */
+
+void SMBNTencrypt(uchar *passwd, uchar *c8, uchar *p24)
+{
+ uchar p21[21];
+
+ memset(p21,'\0',21);
+
+ E_md4hash(passwd, p21);
+ E_P24(p21, c8, p24);
+}
+
#else
void smbencrypt_dummy(void){}
#endif
diff -u -r --new-file last-version/source/smbpass.c samba-1.9.14p3/source/smbpass.c
--- last-version/source/smbpass.c Sun Sep 10 23:10:41 1995
+++ samba-1.9.14p3/source/smbpass.c Mon Nov 6 16:54:57 1995
@@ -1,281 +1,304 @@
#ifdef SMB_PASSWD
-/*
- Unix SMB/Netbios implementation.
- Version 1.9.
- SMB parameters and setup
- Copyright (C) Andrew Tridgell 1992-1995
- Modified by Jeremy Allison 1995.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
+/*
+ * Unix SMB/Netbios implementation. Version 1.9. SMB parameters and setup
+ * Copyright (C) Andrew Tridgell 1992-1995 Modified by Jeremy Allison 1995.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 675
+ * Mass Ave, Cambridge, MA 02139, USA.
+ */
#include "includes.h"
#include "loadparm.h"
-extern int DEBUGLEVEL;
+extern int DEBUGLEVEL;
-int gotalarm;
+int gotalarm;
-void gotalarm_sig()
+void
+gotalarm_sig()
{
- gotalarm = 1;
+ gotalarm = 1;
}
-int do_pw_lock(int fd, int waitsecs, int type)
+int
+do_pw_lock(int fd, int waitsecs, int type)
{
- struct flock lock;
- int ret;
+ struct flock lock;
+ int ret;
- gotalarm = 0;
+ gotalarm = 0;
signal(SIGALRM, SIGNAL_CAST gotalarm_sig);
- lock.l_type = type;
- lock.l_whence = SEEK_SET;
- lock.l_start = 0;
- lock.l_len = 1;
- lock.l_pid = 0;
-
- alarm(5);
- ret = fcntl(fd, F_SETLKW, &lock);
- alarm(0);
- signal( SIGALRM, SIGNAL_CAST SIG_DFL);
-
- if(gotalarm) {
- DEBUG(0,("do_pw_lock: failed to %s SMB passwd file.\n",
- type == F_UNLCK ? "unlock" : "lock" ));
- return -1;
- }
- return ret;
+ lock.l_type = type;
+ lock.l_whence = SEEK_SET;
+ lock.l_start = 0;
+ lock.l_len = 1;
+ lock.l_pid = 0;
+
+ alarm(5);
+ ret = fcntl(fd, F_SETLKW, &lock);
+ alarm(0);
+ signal(SIGALRM, SIGNAL_CAST SIG_DFL);
+
+ if (gotalarm) {
+ DEBUG(0, ("do_pw_lock: failed to %s SMB passwd file.\n",
+ type == F_UNLCK ? "unlock" : "lock"));
+ return -1;
+ }
+ return ret;
}
-int pw_file_lock(const char *name, int type, int secs)
+int
+pw_file_lock(char *name, int type, int secs)
{
- int fd = open(name,O_RDWR|O_CREAT,0666);
- if (fd < 0) return(-1);
- if(do_pw_lock(fd, secs, type))
- {
+ int fd = open(name, O_RDWR | O_CREAT, 0666);
+ if (fd < 0)
+ return (-1);
+ if (do_pw_lock(fd, secs, type)) {
close(fd);
return -1;
- }
+ }
return fd;
}
-int pw_file_unlock(int fd)
+int
+pw_file_unlock(int fd)
{
do_pw_lock(fd, 5, F_UNLCK);
return close(fd);
}
/*
- * Routine to search the smbpasswd file for an
- * entry matching the username.
+ * Routine to get the next 32 hex characters and turn them
+ * into a 16 byte array.
*/
-struct smb_passwd *get_smbpwnam(char *name)
+
+static int gethexpwd(char *p, char *pwd)
{
- /* Static buffers we will return. */
- static struct smb_passwd pw_buf;
- static pstring user_name;
- static unsigned char smbpwd[16];
- char linebuf[256];
- char readbuf[16*1024];
- unsigned char c;
- unsigned char *p;
- long uidval;
- long linebuf_len;
- unsigned char lonybble, hinybble;
- int i;
- FILE *fp;
- int lockfd;
- char *pfile = lp_smb_passwd_file();
-
- if (!*pfile) {
- DEBUG(0,("No SMB password file set\n"));
- return(NULL);
- }
-
- DEBUG(10,("get_smbpwnam: opening file %s\n", pfile));
-
- fp = fopen(pfile,"r");
-
- if(fp == NULL)
- {
- DEBUG(0,("get_smbpwnam: unable to open file %s\n", pfile));
- return NULL;
- }
-
- /* Set a 16k buffer to do more efficient reads */
- setvbuf(fp, readbuf, _IOFBF, sizeof(readbuf));
-
- if((lockfd = pw_file_lock(pfile,F_RDLCK,5))<0) {
- DEBUG(0,("get_smbpwnam: unable to lock file %s\n", pfile));
- fclose(fp);
- return NULL;
- }
-
- /* make sure it is only rw by the owner */
- chmod(pfile,0600);
-
- /* We have a read lock on the file. */
- /* Scan the file, a line at a time and
- check if the name matches. */
- while(!feof(fp))
- {
- linebuf[0] = '\0';
-
- fgets(linebuf, 256, fp);
- if(ferror(fp))
- {
- fclose(fp);
- pw_file_unlock(lockfd);
- return NULL;
+ int i;
+ unsigned char lonybble, hinybble;
+ char *hexchars = "0123456789ABCDEF";
+ char *p1, *p2;
+
+ for (i = 0; i < 32; i += 2) {
+ hinybble = toupper(p[i]);
+ lonybble = toupper(p[i + 1]);
+
+ p1 = strchr(hexchars, hinybble);
+ p2 = strchr(hexchars, lonybble);
+ if (!p1 || !p2)
+ return (False);
+ hinybble = PTR_DIFF(p1, hexchars);
+ lonybble = PTR_DIFF(p2, hexchars);
+
+ pwd[i / 2] = (hinybble << 4) | lonybble;
}
+ return (True);
+}
- /* Check if the string is terminated with a newline -
- if not then we must keep reading and discard until
- we get one.
- */
- linebuf_len = strlen(linebuf);
- if(linebuf[linebuf_len-1] != '\n')
- {
- c = '\0';
- while(!ferror(fp) && !feof(fp))
- {
- c = fgetc(fp);
- if(c == '\n')
- break;
- }
+/*
+ * Routine to search the smbpasswd file for an entry matching the username.
+ */
+struct smb_passwd *
+get_smbpwnam(char *name)
+{
+ /* Static buffers we will return. */
+ static struct smb_passwd pw_buf;
+ static pstring user_name;
+ static unsigned char smbpwd[16];
+ static unsigned char smbntpwd[16];
+ char linebuf[256];
+ char readbuf[16 * 1024];
+ unsigned char c;
+ unsigned char *p;
+ long uidval;
+ long linebuf_len;
+ FILE *fp;
+ int lockfd;
+ char *pfile = lp_smb_passwd_file();
+
+ if (!*pfile) {
+ DEBUG(0, ("No SMB password file set\n"));
+ return (NULL);
}
- else
- linebuf[linebuf_len-1] = '\0';
+ DEBUG(10, ("get_smbpwnam: opening file %s\n", pfile));
-#ifdef DEBUG_PASSWORD
- DEBUG(100, ("get_smbpwnam: got line |%s|\n", linebuf));
-#endif
- if((linebuf[0] == 0) && feof(fp))
- {
- DEBUG(4,("get_smbpwnam: end of file reached\n"));
- break;
- }
- /* The line we have should be of the form :-
-
- username:uid:[32hex bytes]:....other flags presently ignored....
-
- */
+ fp = fopen(pfile, "r");
- if(linebuf[0] == '#' || linebuf[0] == '\0')
- {
- DEBUG(6,("get_smbpwnam: skipping comment or blank line\n"));
- continue;
- }
- p = (unsigned char *)strchr(linebuf, ':');
- if( p == NULL)
- {
- DEBUG(0,("get_smbpwnam: malformed password entry (no :)\n"));
- continue;
+ if (fp == NULL) {
+ DEBUG(0, ("get_smbpwnam: unable to open file %s\n", pfile));
+ return NULL;
}
- /* As 256 is shorter than a pstring we don't
- need to check length here - if this ever changes.... */
- strncpy(user_name, linebuf, PTR_DIFF(p,linebuf));
- user_name[PTR_DIFF(p,linebuf)] = '\0';
- if(!strequal(user_name, name))
- continue;
-
- /* User name matches - get uid and password */
- p++; /* Go past ':' */
- if(!isdigit(*p)) {
- DEBUG(0,("get_smbpwnam: malformed password entry (uid not number)\n"));
- fclose(fp);
- pw_file_unlock(lockfd);
- return NULL;
- }
+ /* Set a 16k buffer to do more efficient reads */
+ setvbuf(fp, readbuf, _IOFBF, sizeof(readbuf));
- uidval = atoi((char *)p);
- while (*p && isdigit(*p)) p++;
- if(*p != ':') {
- DEBUG(0,("get_smbpwnam: malformed password entry (no : after uid)\n"));
- fclose(fp);
- pw_file_unlock(lockfd);
- return NULL;
- }
+ if ((lockfd = pw_file_lock(pfile, F_RDLCK, 5)) < 0) {
+ DEBUG(0, ("get_smbpwnam: unable to lock file %s\n", pfile));
+ fclose(fp);
+ return NULL;
+ }
+ /* make sure it is only rw by the owner */
+ chmod(pfile, 0600);
- /* Now get the password value - this should be 32 hex digits which
- are the ascii representations of a 16 byte string. Get two at
- a time and put them into the password.
+ /* We have a read lock on the file. */
+ /*
+ * Scan the file, a line at a time and check if the name matches.
*/
- p++;
- if(*p == '*' || *p == 'X') {
- /* Password deliberately invalid - end here. */
- DEBUG(10,("get_smbpwnam: entry invalidated for user %s\n",user_name));
- fclose(fp);
- pw_file_unlock(lockfd);
- return NULL;
- }
- if(linebuf_len < (PTR_DIFF(p,linebuf) + 33)) {
- DEBUG(0,("get_smbpwnam: malformed password entry (passwd too short)\n"));
- fclose(fp);
- pw_file_unlock(lockfd);
- return(False);
- }
+ while (!feof(fp)) {
+ linebuf[0] = '\0';
+
+ fgets(linebuf, 256, fp);
+ if (ferror(fp)) {
+ fclose(fp);
+ pw_file_unlock(lockfd);
+ return NULL;
+ }
+ /*
+ * Check if the string is terminated with a newline - if not
+ * then we must keep reading and discard until we get one.
+ */
+ linebuf_len = strlen(linebuf);
+ if (linebuf[linebuf_len - 1] != '\n') {
+ c = '\0';
+ while (!ferror(fp) && !feof(fp)) {
+ c = fgetc(fp);
+ if (c == '\n')
+ break;
+ }
+ } else
+ linebuf[linebuf_len - 1] = '\0';
+
+#ifdef DEBUG_PASSWORD
+ DEBUG(100, ("get_smbpwnam: got line |%s|\n", linebuf));
+#endif
+ if ((linebuf[0] == 0) && feof(fp)) {
+ DEBUG(4, ("get_smbpwnam: end of file reached\n"));
+ break;
+ }
+ /*
+ * The line we have should be of the form :-
+ *
+ * username:uid:[32hex bytes]:....other flags presently
+ * ignored....
+ *
+ * or,
+ *
+ * username:uid:[32hex bytes]:[32hex bytes]:....ignored....
+ *
+ * if Windows NT compatible passwords are also present.
+ */
+
+ if (linebuf[0] == '#' || linebuf[0] == '\0') {
+ DEBUG(6, ("get_smbpwnam: skipping comment or blank line\n"));
+ continue;
+ }
+ p = (unsigned char *) strchr(linebuf, ':');
+ if (p == NULL) {
+ DEBUG(0, ("get_smbpwnam: malformed password entry (no :)\n"));
+ continue;
+ }
+ /*
+ * As 256 is shorter than a pstring we don't need to check
+ * length here - if this ever changes....
+ */
+ strncpy(user_name, linebuf, PTR_DIFF(p, linebuf));
+ user_name[PTR_DIFF(p, linebuf)] = '\0';
+ if (!strequal(user_name, name))
+ continue;
+
+ /* User name matches - get uid and password */
+ p++; /* Go past ':' */
+ if (!isdigit(*p)) {
+ DEBUG(0, ("get_smbpwnam: malformed password entry (uid not number)\n"));
+ fclose(fp);
+ pw_file_unlock(lockfd);
+ return NULL;
+ }
+ uidval = atoi((char *) p);
+ while (*p && isdigit(*p))
+ p++;
+ if (*p != ':') {
+ DEBUG(0, ("get_smbpwnam: malformed password entry (no : after uid)\n"));
+ fclose(fp);
+ pw_file_unlock(lockfd);
+ return NULL;
+ }
+ /*
+ * Now get the password value - this should be 32 hex digits
+ * which are the ascii representations of a 16 byte string.
+ * Get two at a time and put them into the password.
+ */
+ p++;
+ if (*p == '*' || *p == 'X') {
+ /* Password deliberately invalid - end here. */
+ DEBUG(10, ("get_smbpwnam: entry invalidated for user %s\n", user_name));
+ fclose(fp);
+ pw_file_unlock(lockfd);
+ return NULL;
+ }
+ if (linebuf_len < (PTR_DIFF(p, linebuf) + 33)) {
+ DEBUG(0, ("get_smbpwnam: malformed password entry (passwd too short)\n"));
+ fclose(fp);
+ pw_file_unlock(lockfd);
+ return (False);
+ }
+ if (p[32] != ':') {
+ DEBUG(0, ("get_smbpwnam: malformed password entry (no terminating :)\n"));
+ fclose(fp);
+ pw_file_unlock(lockfd);
+ return NULL;
+ }
+ if (!strncasecmp((char *) p, "NO PASSWORD", 11)) {
+ pw_buf.smb_passwd = NULL;
+ } else {
+ if(!gethexpwd(p,smbpwd)) {
+ DEBUG(0, ("Malformed Lanman password entry (non hex chars)\n"));
+ fclose(fp);
+ pw_file_unlock(lockfd);
+ return NULL;
+ }
+ pw_buf.smb_passwd = smbpwd;
+ }
+ pw_buf.smb_name = user_name;
+ pw_buf.smb_userid = uidval;
+ pw_buf.smb_nt_passwd = NULL;
+
+ /* Now check if the NT compatible password is
+ available. */
+ p += 33; /* Move to the first character of the line after
+ the lanman password. */
+ if ((linebuf_len >= (PTR_DIFF(p, linebuf) + 33)) && (p[32] == ':')) {
+ if (*p != '*' && *p != 'X') {
+ if(gethexpwd(p,smbntpwd))
+ pw_buf.smb_nt_passwd = smbntpwd;
+ }
+ }
+
+ fclose(fp);
+ pw_file_unlock(lockfd);
+ DEBUG(5, ("get_smbpwname: returning passwd entry for user %s, uid %d\n",
+ user_name, uidval));
+ return &pw_buf;
+ }
- if(p[32] != ':') {
- DEBUG(0,("get_smbpwnam: malformed password entry (no terminating :)\n"));
fclose(fp);
pw_file_unlock(lockfd);
return NULL;
- }
-
- if (!strncasecmp((char *)p,"NO PASSWORD", 11)) {
- pw_buf.smb_passwd = NULL;
- } else {
- char *hexchars = "0123456789ABCDEF";
- char *p1,*p2;
- for(i = 0; i < 32; i += 2)
- {
- hinybble = toupper(p[i]);
- lonybble = toupper(p[i+1]);
-
- p1 = strchr(hexchars,hinybble);
- p2 = strchr(hexchars,lonybble);
- if (!p1 || !p2) {
- DEBUG(0,("Malformed password entry (non hex chars)\n"));
- fclose(fp);
- pw_file_unlock(lockfd);
- return NULL;
- }
-
- hinybble = PTR_DIFF(p1,hexchars);
- lonybble = PTR_DIFF(p2,hexchars);
-
- smbpwd[i/2] = (hinybble << 4) | lonybble;
- }
- pw_buf.smb_passwd = smbpwd;
- }
- pw_buf.smb_name = user_name;
- pw_buf.smb_userid = uidval;
- fclose(fp);
- pw_file_unlock(lockfd);
- DEBUG(5,("get_smbpwname: returning passwd entry for user %s, uid %d\n",
- user_name, uidval));
- return &pw_buf;
- }
-
- fclose(fp);
- pw_file_unlock(lockfd);
- return NULL;
}
#else
-void smbpass_dummy(void){} /* To avoid compiler complaints */
+void
+smbpass_dummy(void)
+{
+} /* To avoid compiler complaints */
#endif
-
diff -u -r --new-file last-version/source/smbpass.h samba-1.9.14p3/source/smbpass.h
--- last-version/source/smbpass.h Sun Sep 10 23:10:47 1995
+++ samba-1.9.14p3/source/smbpass.h Mon Nov 6 16:54:56 1995
@@ -25,6 +25,7 @@
int smb_userid;
char *smb_name;
unsigned char *smb_passwd; /* Null if no password */
+ unsigned char *smb_nt_passwd; /* Null if no password */
/* Other fields / flags may be added later */
};
@@ -39,9 +40,11 @@
void str_to_key(unsigned char *str,unsigned char *key);
void E_P16(uchar *p14,uchar *p16);
void E_P24(unsigned char *p21, unsigned char *c8, unsigned char *p24);
+void E_md4hash(uchar *passwd,uchar *p16);
void SMBencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24);
+void SMB_nt_encrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24);
/* Password file lock/unlock routines */
-int pw_file_lock(const char *name, int type, int secs);
+int pw_file_lock(char *name, int type, int secs);
int pw_file_unlock(int fd);
#endif
diff -u -r --new-file last-version/source/smbpasswd.c samba-1.9.14p3/source/smbpasswd.c
--- last-version/source/smbpasswd.c Sun Sep 10 23:28:28 1995
+++ samba-1.9.14p3/source/smbpasswd.c Mon Nov 6 16:54:38 1995
@@ -1,381 +1,447 @@
#ifdef SMB_PASSWD
-/*
- Unix SMB/Netbios implementation.
- Version 1.9.
- smbpasswd module.
- Copyright (C) Jeremy Allison 1995.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
+/*
+ * Unix SMB/Netbios implementation. Version 1.9. smbpasswd module. Copyright
+ * (C) Jeremy Allison 1995.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 675
+ * Mass Ave, Cambridge, MA 02139, USA.
+ */
#include "includes.h"
#include "des.h"
#ifdef SMBGETPASS
-extern char *getsmbpass(const char *);
+extern char *getsmbpass(char *);
#define getpass getsmbpass
#endif
/* Static buffers we will return. */
static struct smb_passwd pw_buf;
-static pstring user_name;
+static pstring user_name;
static unsigned char smbpwd[16];
+static unsigned char smbntpwd[16];
-struct smb_passwd *_my_get_smbpwnam(FILE *fp,char *name, BOOL *valid_old_pwd, long *pwd_seekpos)
+static int gethexpwd(char *p, char *pwd)
{
- char linebuf[256];
- unsigned char c;
- unsigned char *p;
- long uidval;
- long linebuf_len;
- unsigned char lonybble, hinybble;
- int i;
-
- /* Scan the file, a line at a time and
- check if the name matches. */
- while(!feof(fp))
- {
- linebuf[0] = '\0';
- *pwd_seekpos = ftell(fp);
+ int i;
+ unsigned char lonybble, hinybble;
+ char *hexchars = "0123456789ABCDEF";
+ char *p1, *p2;
+ for (i = 0; i < 32; i += 2) {
+ hinybble = toupper(p[i]);
+ lonybble = toupper(p[i + 1]);
+
+ p1 = strchr(hexchars, hinybble);
+ p2 = strchr(hexchars, lonybble);
+ if (!p1 || !p2)
+ return (False);
- fgets(linebuf, 256, fp);
- if(ferror(fp))
- return NULL;
+ hinybble = PTR_DIFF(p1, hexchars);
+ lonybble = PTR_DIFF(p2, hexchars);
- /* Check if the string is terminated with a newline -
- if not then we must keep reading and discard until
- we get one.
- */
- linebuf_len = strlen(linebuf);
- if(linebuf[linebuf_len-1] != '\n')
- {
- c = '\0';
- while(!ferror(fp) && !feof(fp))
- {
- c = fgetc(fp);
- if(c == '\n')
- break;
- }
- }
- else
- linebuf[linebuf_len-1] = '\0';
-
- if((linebuf[0] == 0) && feof(fp))
- break;
- /* The line we have should be of the form :-
+ pwd[i / 2] = (hinybble << 4) | lonybble;
+ }
+ return (True);
+}
- username:uid:[32hex bytes]:....other flags presently ignored....
- */
+struct smb_passwd *
+_my_get_smbpwnam(FILE * fp, char *name, BOOL * valid_old_pwd,
+ BOOL *got_valid_nt_entry, long *pwd_seekpos)
+{
+ char linebuf[256];
+ unsigned char c;
+ unsigned char *p;
+ long uidval;
+ long linebuf_len;
- if(linebuf[0] == '#' || linebuf[0] == '\0')
- continue;
- p = (unsigned char *)strchr(linebuf, ':');
- if( p == NULL)
- continue;
- /* As 256 is shorter than a pstring we don't
- need to check length here - if this ever changes.... */
- strncpy( user_name, linebuf, PTR_DIFF(p,linebuf));
- user_name[PTR_DIFF(p,linebuf)] = '\0';
- if(!strequal(user_name, name))
- continue;
-
- /* User name matches - get uid and password */
- p++; /* Go past ':' */
- if(!isdigit(*p))
- return(False);
-
- uidval = atoi((char *)p);
- while (*p && isdigit(*p)) p++;
-
- if(*p != ':')
- return(False);
-
- /* Now get the password value - this should be 32 hex digits which
- are the ascii representations of a 16 byte string. Get two at
- a time and put them into the password.
+ /*
+ * Scan the file, a line at a time and check if the name matches.
*/
- p++;
- *pwd_seekpos += PTR_DIFF(p,linebuf); /* Save exact position of
- passwd in file - this is used
- by smbpasswd.c
- */
- if(*p == '*' || *p == 'X')
- {
- /* Password deliberately invalid - end here. */
- *valid_old_pwd = False;
- pw_buf.smb_name = user_name;
- pw_buf.smb_userid = uidval;
- return(&pw_buf);
- }
- if(linebuf_len < (PTR_DIFF(p,linebuf) + 33))
- return(False);
-
- if(p[32] != ':')
- return(False);
-
- if(!strncasecmp(p,"NO PASSWORD",11)) {
- pw_buf.smb_passwd = NULL; /* No password */
- } else {
- char *hexchars = "0123456789ABCDEF";
- char *p1,*p2;
- for(i = 0; i < 32; i += 2)
- {
- hinybble = toupper(p[i]);
- lonybble = toupper(p[i+1]);
-
- p1 = strchr(hexchars,hinybble);
- p2 = strchr(hexchars,lonybble);
- if (!p1 || !p2)
- return(False);
-
- hinybble = PTR_DIFF(p1,hexchars);
- lonybble = PTR_DIFF(p2,hexchars);
-
- smbpwd[i/2] = (hinybble << 4) | lonybble;
- }
- pw_buf.smb_passwd = smbpwd;
- }
-
- pw_buf.smb_name = user_name;
- pw_buf.smb_userid = uidval;
- *valid_old_pwd = True;
- return &pw_buf;
- }
- return NULL;
+ while (!feof(fp)) {
+ linebuf[0] = '\0';
+ *pwd_seekpos = ftell(fp);
+
+ fgets(linebuf, 256, fp);
+ if (ferror(fp))
+ return NULL;
+
+ /*
+ * Check if the string is terminated with a newline - if not
+ * then we must keep reading and discard until we get one.
+ */
+ linebuf_len = strlen(linebuf);
+ if (linebuf[linebuf_len - 1] != '\n') {
+ c = '\0';
+ while (!ferror(fp) && !feof(fp)) {
+ c = fgetc(fp);
+ if (c == '\n')
+ break;
+ }
+ } else
+ linebuf[linebuf_len - 1] = '\0';
+
+ if ((linebuf[0] == 0) && feof(fp))
+ break;
+ /*
+ * The line we have should be of the form :-
+ *
+ * username:uid:[32hex bytes]:....other flags presently
+ * ignored....
+ *
+ * or,
+ *
+ * username:uid:[32hex bytes]:[32hex bytes]:....ignored....
+ *
+ * if Windows NT compatible passwords are also present.
+ */
+
+ if (linebuf[0] == '#' || linebuf[0] == '\0')
+ continue;
+ p = (unsigned char *) strchr(linebuf, ':');
+ if (p == NULL)
+ continue;
+ /*
+ * As 256 is shorter than a pstring we don't need to check
+ * length here - if this ever changes....
+ */
+ strncpy(user_name, linebuf, PTR_DIFF(p, linebuf));
+ user_name[PTR_DIFF(p, linebuf)] = '\0';
+ if (!strequal(user_name, name))
+ continue;
+
+ /* User name matches - get uid and password */
+ p++; /* Go past ':' */
+ if (!isdigit(*p))
+ return (False);
+
+ uidval = atoi((char *) p);
+ while (*p && isdigit(*p))
+ p++;
+
+ if (*p != ':')
+ return (False);
+
+ /*
+ * Now get the password value - this should be 32 hex digits
+ * which are the ascii representations of a 16 byte string.
+ * Get two at a time and put them into the password.
+ */
+ p++;
+ *pwd_seekpos += PTR_DIFF(p, linebuf); /* Save exact position
+ * of passwd in file -
+ * this is used by
+ * smbpasswd.c */
+ if (*p == '*' || *p == 'X') {
+ /* Password deliberately invalid - end here. */
+ *valid_old_pwd = False;
+ *got_valid_nt_entry = False;
+ pw_buf.smb_name = user_name;
+ pw_buf.smb_userid = uidval;
+ pw_buf.smb_passwd = NULL; /* No password */
+ pw_buf.smb_nt_passwd = NULL; /* No password */
+ return (&pw_buf);
+ }
+ if (linebuf_len < (PTR_DIFF(p, linebuf) + 33))
+ return (False);
+
+ if (p[32] != ':')
+ return (False);
+
+ if (!strncasecmp(p, "NO PASSWORD", 11)) {
+ pw_buf.smb_passwd = NULL; /* No password */
+ } else {
+ if(!gethexpwd(p,smbpwd))
+ return False;
+ pw_buf.smb_passwd = smbpwd;
+ }
+
+ pw_buf.smb_name = user_name;
+ pw_buf.smb_userid = uidval;
+ pw_buf.smb_nt_passwd = NULL;
+ *got_valid_nt_entry = False;
+ *valid_old_pwd = True;
+
+ /* Now check if the NT compatible password is
+ available. */
+ p += 33; /* Move to the first character of the line after
+ the lanman password. */
+ if ((linebuf_len >= (PTR_DIFF(p, linebuf) + 33)) && (p[32] == ':')) {
+ /* NT Entry was valid - even if 'X' or '*', can be overwritten */
+ *got_valid_nt_entry = True;
+ if (*p != '*' && *p != 'X') {
+ if(gethexpwd(p,smbntpwd))
+ pw_buf.smb_nt_passwd = smbntpwd;
+ }
+ }
+ return &pw_buf;
+ }
+ return NULL;
}
/*
* Print command usage on stderr and die.
*/
-void usage(char *name)
+void
+usage(char *name)
{
fprintf(stderr, "Usage is : %s [username]\n", name);
exit(1);
}
-int main(int argc, char **argv)
+int
+main(int argc, char **argv)
{
- int real_uid;
- struct passwd *pwd;
- fstring old_passwd;
- uchar old_p16[16];
- fstring new_passwd;
- uchar new_p16[16];
- char *p;
- struct smb_passwd *smb_pwent;
- FILE *fp;
- BOOL valid_old_pwd = False;
- long seekpos;
- int pwfd;
- char ascii_p16[33];
- char c;
- int ret, i, err;
- int lockfd=-1;
- char *pfile = SMB_PASSWD_FILE;
- char readbuf[16*1024];
+ int real_uid;
+ struct passwd *pwd;
+ fstring old_passwd;
+ uchar old_p16[16];
+ uchar old_nt_p16[16];
+ fstring new_passwd;
+ uchar new_p16[16];
+ uchar new_nt_p16[16];
+ char *p;
+ struct smb_passwd *smb_pwent;
+ FILE *fp;
+ BOOL valid_old_pwd = False;
+ BOOL got_valid_nt_entry = False;
+ long seekpos;
+ int pwfd;
+ char ascii_p16[66];
+ char c;
+ int ret, i, err, writelen;
+ int lockfd = -1;
+ char *pfile = SMB_PASSWD_FILE;
+ char readbuf[16 * 1024];
- charset_initialise();
+ charset_initialise();
#ifndef DEBUG_PASSWORD
- /* Check the effective uid */
- if(geteuid() != 0) {
- fprintf(stderr, "%s: Must be setuid root.\n", argv[0]);
- exit(1);
- }
+ /* Check the effective uid */
+ if (geteuid() != 0) {
+ fprintf(stderr, "%s: Must be setuid root.\n", argv[0]);
+ exit(1);
+ }
#endif
- /* Get the real uid */
- real_uid = getuid();
-
- /* Deal with usage problems */
- if( real_uid == 0) {
- /* As root we can change anothers password. */
- if(argc != 1 && argc != 2)
- usage(argv[0]);
- } else if(argc != 1)
- usage(argv[0]);
-
-
- if(real_uid == 0 && argc == 2) {
- /* If we are root we can change anothers password. */
- strncpy( user_name, argv[1], sizeof(user_name)-1);
- user_name[sizeof(user_name)-1] = '\0';
- pwd = getpwnam( user_name );
- } else {
- pwd = getpwuid( real_uid );
- }
-
- if(pwd == 0) {
- fprintf(stderr, "%s: Unable to get UNIX password entry for user.\n", argv[0]);
- exit(1);
- }
-
- /* If we are root we don't ask for the old password. */
- old_passwd[0] = '\0';
- if(real_uid != 0) {
- p = getpass("Old SMB password:");
- strncpy(old_passwd, p, 14);
- old_passwd[14] = '\0';
- strupper(old_passwd);
- }
-
- new_passwd[0] = '\0';
- p = getpass("New SMB password:");
- strncpy(new_passwd, p, 14);
- new_passwd[14] = '\0';
- p = getpass("Retype new SMB password:");
- if(strncmp(p, new_passwd, 14)) {
- fprintf(stderr, "%s: Mismatch - password unchanged.\n", argv[0]);
- exit(1);
- }
- strupper(new_passwd);
-
- if(new_passwd[0] == '\0') {
- printf("Password not set\n");
- exit(0);
- }
-
- /* Calculate the SMB hash functions of
- both old an new passwords. */
-
- memset(old_p16,'\0',16);
- E_P16((uchar *)old_passwd,old_p16);
-
- memset(new_p16,'\0',16);
- E_P16((uchar *)new_passwd,new_p16);
-
- /* Open the smbpaswd file XXXX - we need to parse smb.conf to
- get the filename */
- if((fp = fopen(pfile, "r+")) == NULL) {
- err = errno;
- fprintf(stderr, "%s: Failed to open password file %s.\n",
- argv[0], pfile);
- errno = err;
- perror(argv[0]);
- exit(err);
- }
-
- /* Set read buffer to 16k for effiecient reads */
- setvbuf(fp, readbuf, _IOFBF, sizeof(readbuf));
-
- /* make sure it is only rw by the owner */
- chmod(pfile,0600);
-
- /* Lock the smbpasswd file for write. */
- if((lockfd=pw_file_lock(pfile,F_WRLCK,5))<0) {
- err = errno;
- fprintf(stderr, "%s: Failed to lock password file %s.\n",
- argv[0], pfile);
- fclose(fp);
- errno = err;
- perror(argv[0]);
- exit(err);
- }
-
- /* Get the smb passwd entry for this user */
- smb_pwent = _my_get_smbpwnam(fp, pwd->pw_name, &valid_old_pwd, &seekpos);
- if(smb_pwent == NULL) {
- fprintf(stderr, "%s: Failed to find entry for user %s in file %s.\n",
- argv[0], pwd->pw_name, pfile);
- fclose(fp);
- pw_file_unlock(lockfd);
- exit(1);
- }
-
- /* If we are root we don't need to check the old password. */
- if( real_uid != 0) {
- if( valid_old_pwd == False) {
- fprintf(stderr, "%s: User %s is disabled, plase contact your administrator to enable it.\n", argv[0], pwd->pw_name);
- fclose(fp);
- pw_file_unlock(lockfd);
- exit(1);
+ /* Get the real uid */
+ real_uid = getuid();
+
+ /* Deal with usage problems */
+ if (real_uid == 0) {
+ /* As root we can change anothers password. */
+ if (argc != 1 && argc != 2)
+ usage(argv[0]);
+ } else if (argc != 1)
+ usage(argv[0]);
+
+
+ if (real_uid == 0 && argc == 2) {
+ /* If we are root we can change anothers password. */
+ strncpy(user_name, argv[1], sizeof(user_name) - 1);
+ user_name[sizeof(user_name) - 1] = '\0';
+ pwd = getpwnam(user_name);
+ } else {
+ pwd = getpwuid(real_uid);
+ }
+
+ if (pwd == 0) {
+ fprintf(stderr, "%s: Unable to get UNIX password entry for user.\n", argv[0]);
+ exit(1);
+ }
+ /* If we are root we don't ask for the old password. */
+ old_passwd[0] = '\0';
+ if (real_uid != 0) {
+ p = getpass("Old SMB password:");
+ strncpy(old_passwd, p, sizeof(fstring));
+ old_passwd[sizeof(fstring)-1] = '\0';
+ }
+ new_passwd[0] = '\0';
+ p = getpass("New SMB password:");
+ strncpy(new_passwd, p, sizeof(fstring));
+ new_passwd[sizeof(fstring)-1] = '\0';
+ p = getpass("Retype new SMB password:");
+ if (strcmp(p, new_passwd)) {
+ fprintf(stderr, "%s: Mismatch - password unchanged.\n", argv[0]);
+ exit(1);
+ }
+
+ if (new_passwd[0] == '\0') {
+ printf("Password not set\n");
+ exit(0);
+ }
+
+ /* Calculate the MD4 hash (NT compatible) of the old and new passwords */
+ memset(old_nt_p16, '\0', 16);
+ E_md4hash((uchar *)old_passwd, old_nt_p16);
+
+ memset(new_nt_p16, '\0', 16);
+ E_md4hash((uchar *) new_passwd, new_nt_p16);
+
+ /* Mangle the passwords into Lanman format */
+ old_passwd[14] = '\0';
+ strupper(old_passwd);
+ new_passwd[14] = '\0';
+ strupper(new_passwd);
+
+ /*
+ * Calculate the SMB (lanman) hash functions of both old and new passwords.
+ */
+
+ memset(old_p16, '\0', 16);
+ E_P16((uchar *) old_passwd, old_p16);
+
+ memset(new_p16, '\0', 16);
+ E_P16((uchar *) new_passwd, new_p16);
+
+ /*
+ * Open the smbpaswd file XXXX - we need to parse smb.conf to get the
+ * filename
+ */
+ if ((fp = fopen(pfile, "r+")) == NULL) {
+ err = errno;
+ fprintf(stderr, "%s: Failed to open password file %s.\n",
+ argv[0], pfile);
+ errno = err;
+ perror(argv[0]);
+ exit(err);
+ }
+ /* Set read buffer to 16k for effiecient reads */
+ setvbuf(fp, readbuf, _IOFBF, sizeof(readbuf));
+
+ /* make sure it is only rw by the owner */
+ chmod(pfile, 0600);
+
+ /* Lock the smbpasswd file for write. */
+ if ((lockfd = pw_file_lock(pfile, F_WRLCK, 5)) < 0) {
+ err = errno;
+ fprintf(stderr, "%s: Failed to lock password file %s.\n",
+ argv[0], pfile);
+ fclose(fp);
+ errno = err;
+ perror(argv[0]);
+ exit(err);
+ }
+ /* Get the smb passwd entry for this user */
+ smb_pwent = _my_get_smbpwnam(fp, pwd->pw_name, &valid_old_pwd,
+ &got_valid_nt_entry, &seekpos);
+ if (smb_pwent == NULL) {
+ fprintf(stderr, "%s: Failed to find entry for user %s in file %s.\n",
+ argv[0], pwd->pw_name, pfile);
+ fclose(fp);
+ pw_file_unlock(lockfd);
+ exit(1);
+ }
+ /* If we are root we don't need to check the old password. */
+ if (real_uid != 0) {
+ if ((valid_old_pwd == False) || (smb_pwent->smb_passwd == NULL)) {
+ fprintf(stderr, "%s: User %s is disabled, plase contact your administrator to enable it.\n", argv[0], pwd->pw_name);
+ fclose(fp);
+ pw_file_unlock(lockfd);
+ exit(1);
+ }
+ /* Check the old Lanman password */
+ if (memcmp(old_p16, smb_pwent->smb_passwd, 16)) {
+ fprintf(stderr, "%s: Couldn't change password.\n", argv[0]);
+ fclose(fp);
+ pw_file_unlock(lockfd);
+ exit(1);
+ }
+ /* Check the NT password if it exists */
+ if (smb_pwent->smb_nt_passwd != NULL) {
+ if (memcmp(old_nt_p16, smb_pwent->smb_nt_passwd, 16)) {
+ fprintf(stderr, "%s: Couldn't change password.\n", argv[0]);
+ fclose(fp);
+ pw_file_unlock(lockfd);
+ exit(1);
+ }
+ }
+ }
+ /*
+ * If we get here either we were root or the old password checked out
+ * ok.
+ */
+ /* Create the 32 byte representation of the new p16 */
+ for (i = 0; i < 16; i++) {
+ sprintf(&ascii_p16[i * 2], "%02X", (uchar) new_p16[i]);
+ }
+ if(got_valid_nt_entry) {
+ /* Add on the NT md4 hash */
+ ascii_p16[32] = ':';
+ for (i = 0; i < 16; i++) {
+ sprintf(&ascii_p16[(i * 2)+33], "%02X", (uchar) new_nt_p16[i]);
+ }
}
- /* Check the old passwd (if there was one). */
- if(smb_pwent->smb_passwd != NULL) {
- if( memcmp( old_p16, smb_pwent->smb_passwd, 16)) {
- fprintf(stderr, "%s: Couldn't change password.\n", argv[0]);
+ /*
+ * Do an atomic write into the file at the position defined by
+ * seekpos.
+ */
+ pwfd = fileno(fp);
+ ret = lseek(pwfd, seekpos - 1, SEEK_SET);
+ if (ret != seekpos - 1) {
+ err = errno;
+ fprintf(stderr, "%s: seek fail on file %s.\n",
+ argv[0], pfile);
+ fclose(fp);
+ errno = err;
+ perror(argv[0]);
+ pw_file_unlock(lockfd);
+ exit(1);
+ }
+ /* Sanity check - ensure the character is a ':' */
+ if (read(pwfd, &c, 1) != 1) {
+ err = errno;
+ fprintf(stderr, "%s: read fail on file %s.\n",
+ argv[0], pfile);
+ fclose(fp);
+ errno = err;
+ perror(argv[0]);
+ pw_file_unlock(lockfd);
+ exit(1);
+ }
+ if (c != ':') {
+ fprintf(stderr, "%s: sanity check on passwd file %s failed.\n",
+ argv[0], pfile);
+ fclose(fp);
+ pw_file_unlock(lockfd);
+ exit(1);
+ }
+ writelen = (got_valid_nt_entry) ? 65 : 32;
+ if (write(pwfd, ascii_p16, writelen) != writelen) {
+ err = errno;
+ fprintf(stderr, "%s: write fail in file %s.\n",
+ argv[0], pfile);
+ fclose(fp);
+ errno = err;
+ perror(argv[0]);
+ pw_file_unlock(lockfd);
+ exit(err);
+ }
fclose(fp);
pw_file_unlock(lockfd);
- exit(1);
- }
- }
- }
- /* If we get here either we were root or the old password
- checked out ok. */
- /* Create the 32 byte representation of the new p16 */
- for(i = 0; i < 16; i++) {
- sprintf(&ascii_p16[i*2], "%02X", (uchar)new_p16[i]);
- }
- /* Do an atomic write into the file at the position
- defined by seekpos. */
- pwfd = fileno(fp);
- ret = lseek(pwfd, seekpos - 1, SEEK_SET);
- if(ret != seekpos -1) {
- err = errno;
- fprintf(stderr, "%s: seek fail on file %s.\n",
- argv[0], pfile);
- fclose(fp);
- errno = err;
- perror(argv[0]);
- pw_file_unlock(lockfd);
- exit(1);
- }
- /* Sanity check - ensure the character is a ':' */
- if(read(pwfd,&c,1) != 1) {
- err = errno;
- fprintf(stderr, "%s: read fail on file %s.\n",
- argv[0], pfile);
- fclose(fp);
- errno = err;
- perror(argv[0]);
- pw_file_unlock(lockfd);
- exit(1);
- }
- if(c != ':') {
- fprintf(stderr, "%s: sanity check on passwd file %s failed.\n",
- argv[0], pfile);
- fclose(fp);
- pw_file_unlock(lockfd);
- exit(1);
- }
- if(write(pwfd,ascii_p16,32)!=32) {
- err = errno;
- fprintf(stderr, "%s: write fail in file %s.\n",
- argv[0], pfile);
- fclose(fp);
- errno = err;
- perror(argv[0]);
- pw_file_unlock(lockfd);
- exit(err);
- }
- fclose(fp);
- pw_file_unlock(lockfd);
- printf("Password changed\n");
- return 0;
+ printf("Password changed\n");
+ return 0;
}
#else
#include "includes.h"
-int main(int argc, char **argv)
+int
+main(int argc, char **argv)
{
- printf("smb password encryption not selected in Makefile\n");
- return 0;
+ printf("smb password encryption not selected in Makefile\n");
+ return 0;
}
#endif
-
-
diff -u -r --new-file last-version/source/status.c samba-1.9.14p3/source/status.c
--- last-version/source/status.c Sat Nov 4 23:19:07 1995
+++ samba-1.9.14p3/source/status.c Mon Nov 6 15:55:40 1995
@@ -117,7 +117,8 @@
else
printf("%-10.10s %-8s %-8s %5d %-8s (%s) %s",
crec.name,uidtoname(crec.uid),gidtoname(crec.gid),crec.pid,
- crec.machine,crec.addr,asctime(LocalTime(&crec.start,0)));
+ crec.machine,crec.addr,
+ asctime(LocalTime(&crec.start,GMT_TO_LOCAL)));
}
}
fclose(f);
diff -u -r --new-file last-version/source/trans2.c samba-1.9.14p3/source/trans2.c
--- last-version/source/trans2.c Sat Nov 4 20:29:20 1995
+++ samba-1.9.14p3/source/trans2.c Tue Nov 7 13:59:36 1995
@@ -163,7 +163,7 @@
#if 0
BOOL return_additional_info = BITSETW(params,0);
int16 open_sattr = SVAL(params, 4);
- int32 open_time = IVAL(params,8);
+ time_t open_time = make_unix_date3(params+8);
#endif
int16 open_ofun = SVAL(params,12);
int32 open_size = IVAL(params,14);
@@ -348,7 +348,6 @@
#ifdef MANGLE_LONG_FILENAMES
{
- fstring fname2;
BOOL illegal = False;
int i;
int l = strlen(fname);
@@ -357,8 +356,7 @@
illegal = True;
break;
}
- name_convert(fname2,fname,illegal,SNUM(cnum));
- strcpy(fname,fname2);
+ name_map_mangle(fname,illegal,SNUM(cnum));
}
#endif
@@ -445,13 +443,15 @@
SIVAL(p,0,mode); p += 4;
SIVAL(p,0,strlen(fname)); p += 4;
SIVAL(p,0,0); p += 4;
- if (!is_8_3(fname))
- name_convert(p+2,fname,True,SNUM(cnum));
- else
+ if (!is_8_3(fname)) {
+ strcpy(p+2,unix2dos_format(fname,False));
+ name_map_mangle(p+2,True,SNUM(cnum));
+ } else
*(p+2) = 0;
strupper(p+2);
SSVAL(p,0,strlen(p+2));
p += 2 + 24;
+ /* name_ptr = p; */
strcpy(p,fname); p += strlen(p);
break;
@@ -1208,8 +1208,8 @@
switch (info_level)
{
case 1:
- tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess,False);
- tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite,False);
+ tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
+ tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
mode = SVAL(pdata,l1_attrFile);
size = IVAL(pdata,l1_cbFile);
break;
@@ -1217,15 +1217,15 @@
case 2:
if(IVAL(pdata,l2_cbList) || total_data>32)
return(ERROR(ERRDOS,ERROR_EAS_NOT_SUPPORTED));
- tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess,False);
- tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite,False);
+ tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
+ tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
mode = SVAL(pdata,l1_attrFile);
size = IVAL(pdata,l1_cbFile);
break;
case 3:
- tvs.actime = make_unix_date2(pdata+8,False);
- tvs.modtime = make_unix_date2(pdata+12,False);
+ tvs.actime = make_unix_date2(pdata+8);
+ tvs.modtime = make_unix_date2(pdata+12);
size = IVAL(pdata,16);
mode = IVAL(pdata,24);
break;
@@ -1233,8 +1233,8 @@
case 4:
if (IVAL(pdata,28) != 0 || total_data>36)
return(ERROR(ERRDOS,ERROR_EAS_NOT_SUPPORTED));
- tvs.actime = make_unix_date2(pdata+8,False);
- tvs.modtime = make_unix_date2(pdata+12,False);
+ tvs.actime = make_unix_date2(pdata+8);
+ tvs.modtime = make_unix_date2(pdata+12);
size = IVAL(pdata,16);
mode = IVAL(pdata,24);
break;
diff -u -r --new-file last-version/source/updatesmbpasswd.sh samba-1.9.14p3/source/updatesmbpasswd.sh
--- last-version/source/updatesmbpasswd.sh Thu Jan 1 10:00:00 1970
+++ samba-1.9.14p3/source/updatesmbpasswd.sh Sun Nov 5 15:47:33 1995
@@ -0,0 +1,14 @@
+#!/bin/sh
+nawk 'BEGIN {FS=":"}
+{
+ if( $0 ~ "^#" ) {
+ print $0
+ } else if( (length($4) == 32) && (($4 ~ "^[0-9A-F]*$") || ($4 ~ "^[X]*$") || ( $4 ~ "^[*]*$"))) {
+ print $0
+ } else {
+ printf( "%s:%s:%s:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX:", $1, $2, $3);
+ for(i = 4; i <= NF; i++)
+ printf("%s:", $i)
+ printf("\n")
+ }
+}'
diff -u -r --new-file last-version/source/util.c samba-1.9.14p3/source/util.c
--- last-version/source/util.c Sat Nov 4 22:14:20 1995
+++ samba-1.9.14p3/source/util.c Tue Nov 7 18:24:45 1995
@@ -288,6 +288,11 @@
tm_local = *(localtime(&t));
timediff = mktime(&tm_utc) - mktime(&tm_local);
+
+ if (serverzone == 0) {
+ serverzone = timediff - DSTDiff(t);
+ DEBUG(4,("Serverzone is %d\n",serverzone));
+ }
}
@@ -365,20 +370,10 @@
int TimeDiff(time_t t)
{
static BOOL initialised = False;
- if (!initialised) {TimeInit(); initialised=True;}
+ if (!initialised) {initialised=True; TimeInit();}
return(timediff - DSTDiff(t));
}
-
-/****************************************************************************
-try to optimise the timelocal call, it can be quite expenive on some machines
-****************************************************************************/
-static time_t TimeLocal(struct tm *tm,int timemul)
-{
- time_t ret = mktime(tm);
- return(ret + timemul * TimeDiff(ret));
-}
-
/****************************************************************************
try to optimise the localtime call, it can be quite expenive on some machines
timemul is normally LOCAL_TO_GMT, GMT_TO_LOCAL or 0
@@ -387,7 +382,8 @@
{
time_t t2 = *t;
- t2 += timemul * TimeDiff(t2);
+ if (timemul)
+ t2 += timemul * TimeDiff(t2);
return(gmtime(&t2));
}
@@ -680,6 +676,15 @@
char *StrCpy(char *dest,char *src)
{
char *d = dest;
+
+#if AJT
+ /* I don't want to get lazy with these ... */
+ if (!dest || !src) {
+ DEBUG(0,("ERROR: NULL StrCpy() called!\n"));
+ ajt_panic();
+ }
+#endif
+
if (!dest) return(NULL);
if (!src) {
*dest = 0;
@@ -830,14 +835,15 @@
/*******************************************************************
check if a directory exists
********************************************************************/
-BOOL directory_exist(char *dname)
+BOOL directory_exist(char *dname,struct stat *st)
{
- struct stat st;
+ struct stat st2;
+ if (!st) st = &st2;
- if (sys_stat(dname,&st) != 0)
+ if (sys_stat(dname,st) != 0)
return(False);
- return(S_ISDIR(st.st_mode));
+ return(S_ISDIR(st->st_mode));
}
/*******************************************************************
@@ -851,6 +857,16 @@
return(buf.st_size);
}
+/****************************************************************************
+check if it's a null mtime
+****************************************************************************/
+static BOOL null_mtime(time_t mtime)
+{
+ if (mtime == 0 || mtime == 0xFFFFFFFF)
+ return(True);
+ return(False);
+}
+
/*******************************************************************
create a 16 bit dos packed date
********************************************************************/
@@ -875,6 +891,7 @@
/*******************************************************************
create a 32 bit dos packed date/time from some parameters
+ This takes a GMT time and returns a packed localtime structure
********************************************************************/
static uint32 make_dos_date(time_t unixdate)
{
@@ -891,6 +908,7 @@
/*******************************************************************
put a dos date into a buffer (time/date format)
+This takes GMT time and puts local time in the buffer
********************************************************************/
void put_dos_date(char *buf,int offset,time_t unixdate)
{
@@ -900,6 +918,7 @@
/*******************************************************************
put a dos date into a buffer (date/time format)
+This takes GMT time and puts local time in the buffer
********************************************************************/
void put_dos_date2(char *buf,int offset,time_t unixdate)
{
@@ -908,6 +927,17 @@
SIVAL(buf,offset,x);
}
+/*******************************************************************
+put a dos 32 bit "unix like" date into a buffer. This routine takes
+GMT and converts it to LOCAL time before putting it (most SMBs assume
+localtime for this sort of date)
+********************************************************************/
+void put_dos_date3(char *buf,int offset,time_t unixdate)
+{
+ if (!null_mtime(unixdate))
+ unixdate += GMT_TO_LOCAL*TimeDiff(unixdate);
+ SIVAL(buf,offset,unixdate);
+}
/*******************************************************************
interpret a 32 bit dos packed date/time to some parameters
@@ -928,9 +958,10 @@
}
/*******************************************************************
- create a unix date from a dos date
+ create a unix date (int GMT) from a dos date (which is actually in
+ localtime)
********************************************************************/
-time_t make_unix_date(void *date_ptr,BOOL add_dst)
+time_t make_unix_date(void *date_ptr)
{
uint32 dos_date=0;
struct tm t;
@@ -945,17 +976,18 @@
t.tm_wday = 1;
t.tm_yday = 1;
t.tm_isdst = -1;
-
- ret = TimeLocal(&t,GMT_TO_LOCAL);
+
+ /* mktime() also does the local to GMT time conversion for us. XXXXX
+ Do all unixes do this the same?? */
+ ret = mktime(&t);
- if (add_dst) ret += DSTDiff(ret);
return(ret);
}
/*******************************************************************
- create a unix date from a dos date
+like make_unix_date() but the words are reversed
********************************************************************/
-time_t make_unix_date2(void *date_ptr,BOOL add_dst)
+time_t make_unix_date2(void *date_ptr)
{
uint32 x,x2;
@@ -963,9 +995,20 @@
x2 = ((x&0xFFFF)<<16) | ((x&0xFFFF0000)>>16);
SIVAL(&x,0,x2);
- return(make_unix_date((void *)&x,add_dst));
+ return(make_unix_date((void *)&x));
}
+/*******************************************************************
+ create a unix GMT date from a dos date in 32 bit "unix like" format
+these generally arrive as localtimes, with corresponding DST
+********************************************************************/
+time_t make_unix_date3(void *date_ptr)
+{
+ time_t t = IVAL(date_ptr,0);
+ if (!null_mtime(t))
+ t += LOCAL_TO_GMT*TimeDiff(t);
+ return(t);
+}
/*******************************************************************
return a string representing an attribute for a file
@@ -988,13 +1031,24 @@
/*******************************************************************
+ case insensitive string compararison
+********************************************************************/
+int StrCaseCmp(char *s, char *t)
+{
+ for (; tolower(*s) == tolower(*t); ++s, ++t)
+ if (!*s) return 0;
+
+ return tolower(*s) - tolower(*t);
+}
+
+/*******************************************************************
compare 2 strings
********************************************************************/
BOOL strequal(char *s1,char *s2)
{
if (!s1 || !s2) return(False);
- return(strcasecmp(s1,s2)==0);
+ return(StrCaseCmp(s1,s2)==0);
}
/*******************************************************************
@@ -1877,10 +1931,6 @@
****************************************************************************/
int read_udp_socket(int fd,char *buf,int len)
{
- /* #define NORECVFROM */
-#ifdef NORECVFROM
- return(read_data(fd,buf,len));
-#else
int ret;
struct sockaddr sock;
int socklen;
@@ -1901,7 +1951,6 @@
DEBUG(3,("read %d bytes\n",ret));
return(ret);
-#endif
}
/****************************************************************************
@@ -2539,7 +2588,7 @@
/****************************************************************************
send a single packet to a port on another machine
****************************************************************************/
-BOOL send_packet(char *buf,int len,struct in_addr *ip,int port,int type)
+BOOL send_one_packet(char *buf,int len,struct in_addr *ip,int port,int type)
{
BOOL ret;
int out_fd;
@@ -2620,7 +2669,7 @@
if (strcmp(tok,s) == 0)
return(True);
} else {
- if (strcasecmp(tok,s) == 0)
+ if (StrCaseCmp(tok,s) == 0)
return(True);
}
}
@@ -3261,18 +3310,6 @@
return(ret);
}
-
-/****************************************************************************
-check if it's a null mtime
-****************************************************************************/
-static BOOL null_mtime(time_t mtime)
-{
- if (mtime == 0 || mtime == 0xFFFFFFFF)
- return(True);
- return(False);
-}
-
-
/****************************************************************************
set the time on a file
****************************************************************************/
@@ -3612,11 +3649,16 @@
return(res);
}
-#define TIME_FIXUP_CONSTANT (369.0*365.25*24*60*60 - (3.0*24*60*60 + 6.0*60*60))
+#define TIME_FIXUP_CONSTANT (369.0*365.25*24*60*60-(3.0*24*60*60+6.0*60*60))
/****************************************************************************
interpret an 8 byte "filetime" structure to a time_t
It's originally in "100ns units since jan 1st 1601"
+
+It appears to be kludge-GMT (at least for file listings). This means
+its the GMT you get by taking a localtime and adding the
+serverzone. This is NOT the same as GMT in some cases. This routine
+converts this to real GMT.
****************************************************************************/
time_t interpret_long_date(char *p)
{
@@ -3635,30 +3677,42 @@
/* now adjust by 369 years to make the secs since 1970 */
d -= TIME_FIXUP_CONSTANT;
+ if (d>=MAXINT)
+ return(0);
+
ret = (time_t)(d+0.5);
+ /* this takes us from kludge-GMT to real GMT */
+ ret += TimeDiff(ret) - serverzone;
+
return(ret);
}
/****************************************************************************
put a 8 byte filetime from a time_t
+This takes real GMT as input and converts to kludge-GMT
****************************************************************************/
void put_long_date(char *p,time_t t)
{
uint32 tlow,thigh;
- double d = (double) (t);
+ double d;
if (t==0) {
SIVAL(p,0,0); SIVAL(p,4,0);
return;
}
+ /* this converts GMT to kludge-GMT */
+ t -= TimeDiff(t) - serverzone;
+
+ d = (double) (t);
+
d += TIME_FIXUP_CONSTANT;
- d /= 1.0e-7;
+ d *= 1.0e7;
- thigh = (uint32)(d / (4.0*(double)(1<<30)));
+ thigh = (uint32)(d * (1.0/(4.0*(double)(1<<30))));
tlow = (uint32)(d - ((double)thigh)*4.0*(double)(1<<30));
SIVAL(p,0,tlow);
@@ -3800,7 +3854,7 @@
#ifdef LINUX
fstring s;
sprintf(s,"/proc/%d",pid);
- return(directory_exist(s));
+ return(directory_exist(s,NULL));
#else
{
static BOOL tested=False;
@@ -4137,8 +4191,8 @@
int
rename (zfrom, zto)
- char const *zfrom;
- char const *zto;
+ char *zfrom;
+ char *zto;
{
if (link (zfrom, zto) < 0)
{
@@ -4151,19 +4205,6 @@
return unlink (zfrom);
}
-#endif
-
-#ifdef NOSTRCASECMP
-/*******************************************************************
- case insensitive string compararison
-********************************************************************/
-int strcasecmp(char *s, char *t)
-{
- for (; tolower(*s) == tolower(*t); ++s, ++t)
- if (!*s) return 0;
-
- return tolower(*s) - tolower(*t);
-}
#endif
#if WRAP_MEMCPY
diff -u -r --new-file last-version/source/version.h samba-1.9.14p3/source/version.h
--- last-version/source/version.h Sat Nov 4 23:21:27 1995
+++ samba-1.9.14p3/source/version.h Tue Nov 7 23:00:33 1995
@@ -1 +1 @@
-#define VERSION "1.9.14p2"
+#define VERSION "1.9.14p3"